summaryrefslogtreecommitdiff
path: root/deps/v8
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-07-21 22:20:37 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-07-21 22:20:37 -0700
commitf319e126218dcaafdb0ccf7e968ff839f8327bba (patch)
tree209546d94cdc6c19f69ef92e3ec057301369f416 /deps/v8
parentef1be160d66b7da8bc2da857b1c33c6f680d86f1 (diff)
downloadnodejs-f319e126218dcaafdb0ccf7e968ff839f8327bba.tar.gz
nodejs-f319e126218dcaafdb0ccf7e968ff839f8327bba.tar.bz2
nodejs-f319e126218dcaafdb0ccf7e968ff839f8327bba.zip
Upgrade V8 to 3.4.14
Diffstat (limited to 'deps/v8')
-rw-r--r--deps/v8/ChangeLog39
-rw-r--r--deps/v8/SConstruct14
-rw-r--r--deps/v8/include/v8.h124
-rw-r--r--deps/v8/preparser/preparser-process.cc2
-rw-r--r--deps/v8/samples/shell.cc7
-rwxr-xr-xdeps/v8/src/SConscript19
-rw-r--r--deps/v8/src/api.cc181
-rw-r--r--deps/v8/src/arm/assembler-arm.cc7
-rw-r--r--deps/v8/src/arm/assembler-arm.h14
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc1
-rw-r--r--deps/v8/src/arm/lithium-arm.cc35
-rw-r--r--deps/v8/src/arm/lithium-arm.h40
-rw-r--r--deps/v8/src/arm/lithium-codegen-arm.cc93
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc14
-rw-r--r--deps/v8/src/arm/stub-cache-arm.cc190
-rw-r--r--deps/v8/src/array.js6
-rw-r--r--deps/v8/src/assembler.cc15
-rw-r--r--deps/v8/src/assembler.h6
-rw-r--r--deps/v8/src/ast-inl.h56
-rw-r--r--deps/v8/src/ast.cc68
-rw-r--r--deps/v8/src/ast.h213
-rw-r--r--deps/v8/src/bootstrapper.cc1
-rw-r--r--deps/v8/src/builtins.cc4
-rw-r--r--deps/v8/src/code-stubs.cc5
-rwxr-xr-xdeps/v8/src/compiler.cc2
-rw-r--r--deps/v8/src/compiler.h9
-rw-r--r--deps/v8/src/contexts.h2
-rw-r--r--deps/v8/src/conversions-inl.h7
-rw-r--r--deps/v8/src/d8.cc232
-rw-r--r--deps/v8/src/d8.gyp27
-rw-r--r--deps/v8/src/d8.h111
-rw-r--r--deps/v8/src/debug.cc14
-rw-r--r--deps/v8/src/deoptimizer.cc2
-rw-r--r--deps/v8/src/factory.cc7
-rw-r--r--deps/v8/src/factory.h3
-rw-r--r--deps/v8/src/frames.cc1
-rw-r--r--deps/v8/src/full-codegen.cc1
-rw-r--r--deps/v8/src/globals.h4
-rw-r--r--deps/v8/src/heap.cc33
-rw-r--r--deps/v8/src/heap.h5
-rw-r--r--deps/v8/src/hydrogen-instructions.cc22
-rw-r--r--deps/v8/src/hydrogen-instructions.h101
-rw-r--r--deps/v8/src/hydrogen.cc86
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.cc1
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.cc69
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.h7
-rw-r--r--deps/v8/src/ia32/lithium-ia32.cc35
-rw-r--r--deps/v8/src/ia32/lithium-ia32.h41
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc3
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc157
-rw-r--r--deps/v8/src/jsregexp.cc8
-rw-r--r--deps/v8/src/messages.js19
-rw-r--r--deps/v8/src/mips/assembler-mips.cc7
-rw-r--r--deps/v8/src/mips/assembler-mips.h14
-rw-r--r--deps/v8/src/mips/code-stubs-mips.cc1
-rw-r--r--deps/v8/src/mips/macro-assembler-mips.cc5
-rw-r--r--deps/v8/src/mips/stub-cache-mips.cc189
-rw-r--r--deps/v8/src/mirror-debugger.js41
-rw-r--r--deps/v8/src/natives.h2
-rw-r--r--deps/v8/src/objects-debug.cc3
-rw-r--r--deps/v8/src/objects-inl.h37
-rw-r--r--deps/v8/src/objects.cc255
-rw-r--r--deps/v8/src/objects.h72
-rw-r--r--deps/v8/src/parser.cc186
-rw-r--r--deps/v8/src/parser.h5
-rw-r--r--deps/v8/src/platform-linux.cc1
-rw-r--r--deps/v8/src/platform-nullos.cc5
-rw-r--r--deps/v8/src/platform-posix.cc9
-rw-r--r--deps/v8/src/platform-win32.cc6
-rw-r--r--deps/v8/src/platform.h4
-rw-r--r--deps/v8/src/rewriter.cc16
-rw-r--r--deps/v8/src/runtime.cc273
-rw-r--r--deps/v8/src/runtime.h7
-rw-r--r--deps/v8/src/runtime.js3
-rw-r--r--deps/v8/src/scopes.cc89
-rw-r--r--deps/v8/src/scopes.h6
-rw-r--r--deps/v8/src/spaces.cc57
-rw-r--r--deps/v8/src/spaces.h3
-rw-r--r--deps/v8/src/stub-cache.h5
-rw-r--r--deps/v8/src/v8.cc18
-rw-r--r--deps/v8/src/v8.h3
-rw-r--r--deps/v8/src/v8globals.h10
-rw-r--r--deps/v8/src/v8natives.js43
-rw-r--r--deps/v8/src/version.cc4
-rw-r--r--deps/v8/src/x64/assembler-x64.h2
-rw-r--r--deps/v8/src/x64/code-stubs-x64.cc2
-rw-r--r--deps/v8/src/x64/deoptimizer-x64.cc14
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc2
-rw-r--r--deps/v8/src/x64/lithium-codegen-x64.cc66
-rw-r--r--deps/v8/src/x64/lithium-codegen-x64.h5
-rw-r--r--deps/v8/src/x64/lithium-x64.cc35
-rw-r--r--deps/v8/src/x64/lithium-x64.h40
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc3
-rw-r--r--deps/v8/src/x64/regexp-macro-assembler-x64.cc2
-rw-r--r--deps/v8/src/x64/stub-cache-x64.cc140
-rw-r--r--deps/v8/src/zone.h2
-rw-r--r--deps/v8/test/cctest/SConscript24
-rw-r--r--deps/v8/test/cctest/cctest.gyp41
-rw-r--r--deps/v8/test/cctest/log-eq-of-logging-and-traversal.js22
-rw-r--r--deps/v8/test/cctest/test-api.cc110
-rw-r--r--deps/v8/test/cctest/test-ast.cc2
-rw-r--r--deps/v8/test/cctest/test-log.cc50
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js46
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js40
-rw-r--r--deps/v8/test/mjsunit/debug-receiver.js126
-rw-r--r--deps/v8/test/mjsunit/harmony/proxies.js200
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1560.js68
-rw-r--r--deps/v8/test/mjsunit/regress/regress-798.js1
-rw-r--r--deps/v8/test/mjsunit/unbox-double-arrays.js452
-rw-r--r--deps/v8/test/test262/test262.status84
-rwxr-xr-xdeps/v8/tools/grokdump.py26
111 files changed, 4227 insertions, 920 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 7e7df0680..6901729b0 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,42 @@
+2011-07-20: Version 3.4.14
+
+ Fix the debugger for strict-mode functions. (Chromium issue 89236)
+
+ Add GetPropertyAttribute method for Object in the API. (Patch by Peter Varga)
+
+ Fix -Wunused-but-set-variable for gcc-4.6 on x64. (Issue 1291)
+
+
+2011-07-18: Version 3.4.13
+
+ Improved debugger support to allow inspection of optimized frames (issue
+ 1140).
+
+ Fixed a bug in prototype transitions cache clearing introduced by r8165.
+
+ Fixed shortcutting bug in HInferRepresentation. Patch by Andy Wingo.
+
+ Fixed a memory leak in sample/shell.cc (dispose semaphores).
+
+ Simplified HClampToUint8. Patch by Andy Wingo.
+
+ Exposed APIs for detecting boxed primitives, native errors. Patch by
+ Luke Zarko.
+
+ Added map check for COW elements to crankshaft array handling code
+ (issue 1560).
+
+ Sample shell and (a light version of) D8 links against a shared library
+ now.
+
+ Fixed bug in array filter and reduce functions (issue 1559).
+
+ Avoid TLS load in AstNode constructor.
+
+ Introduced a random entropy source which can optionally be provided at
+ initialization. (Chromium issue 89462).
+
+
2011-07-13: Version 3.4.12
Added --prof profiling option to d8 shell.
diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct
index 5276ce2ca..8e16a7824 100644
--- a/deps/v8/SConstruct
+++ b/deps/v8/SConstruct
@@ -404,6 +404,7 @@ CCTEST_EXTRA_FLAGS = {
},
'os:linux': {
'LIBS': ['pthread'],
+ 'CCFLAGS': ['-Wno-unused-but-set-variable'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -773,6 +774,13 @@ PREPARSER_FLAGS = {
D8_FLAGS = {
+ 'all': {
+ 'library:shared': {
+ 'CPPDEFINES': ['V8_SHARED'],
+ 'LIBS': ['v8'],
+ 'LIBPATH': ['.']
+ },
+ },
'gcc': {
'all': {
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
@@ -1370,7 +1378,11 @@ def BuildSpecific(env, mode, env_overrides, tools):
d8_env = Environment(tools=tools)
d8_env.Replace(**context.flags['d8'])
context.ApplyEnvOverrides(d8_env)
- shell = d8_env.Program('d8' + suffix, object_files + shell_files)
+ if context.options['library'] == 'static':
+ shell = d8_env.Program('d8' + suffix, object_files + shell_files)
+ else:
+ shell = d8_env.Program('d8' + suffix, shell_files)
+ d8_env.Depends(shell, library)
context.d8_targets.append(shell)
for sample in context.samples:
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
index 087241106..f4f81e4c7 100644
--- a/deps/v8/include/v8.h
+++ b/deps/v8/include/v8.h
@@ -80,9 +80,11 @@ namespace v8 {
class Context;
class String;
+class StringObject;
class Value;
class Utils;
class Number;
+class NumberObject;
class Object;
class Array;
class Int32;
@@ -90,6 +92,7 @@ class Uint32;
class External;
class Primitive;
class Boolean;
+class BooleanObject;
class Integer;
class Function;
class Date;
@@ -929,6 +932,26 @@ class Value : public Data {
V8EXPORT bool IsDate() const;
/**
+ * Returns true if this value is a Boolean object.
+ */
+ V8EXPORT bool IsBooleanObject() const;
+
+ /**
+ * Returns true if this value is a Number object.
+ */
+ V8EXPORT bool IsNumberObject() const;
+
+ /**
+ * Returns true if this value is a String object.
+ */
+ V8EXPORT bool IsStringObject() const;
+
+ /**
+ * Returns true if this value is a NativeError.
+ */
+ V8EXPORT bool IsNativeError() const;
+
+ /**
* Returns true if this value is a RegExp.
*/
V8EXPORT bool IsRegExp() const;
@@ -1435,6 +1458,13 @@ class Object : public Value {
V8EXPORT Local<Value> Get(uint32_t index);
+ /**
+ * Gets the property attributes of a property which can be None or
+ * any combination of ReadOnly, DontEnum and DontDelete. Returns
+ * None when the property doesn't exist.
+ */
+ V8EXPORT PropertyAttribute GetPropertyAttributes(Handle<Value> key);
+
// TODO(1245389): Replace the type-specific versions of these
// functions with generic ones that accept a Handle<Value> key.
V8EXPORT bool Has(Handle<String> key);
@@ -1745,6 +1775,63 @@ class Date : public Object {
/**
+ * A Number object (ECMA-262, 4.3.21).
+ */
+class NumberObject : public Object {
+ public:
+ V8EXPORT static Local<Value> New(double value);
+
+ /**
+ * Returns the Number held by the object.
+ */
+ V8EXPORT double NumberValue() const;
+
+ static inline NumberObject* Cast(v8::Value* obj);
+
+ private:
+ V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A Boolean object (ECMA-262, 4.3.15).
+ */
+class BooleanObject : public Object {
+ public:
+ V8EXPORT static Local<Value> New(bool value);
+
+ /**
+ * Returns the Boolean held by the object.
+ */
+ V8EXPORT bool BooleanValue() const;
+
+ static inline BooleanObject* Cast(v8::Value* obj);
+
+ private:
+ V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A String object (ECMA-262, 4.3.18).
+ */
+class StringObject : public Object {
+ public:
+ V8EXPORT static Local<Value> New(Handle<String> value);
+
+ /**
+ * Returns the String held by the object.
+ */
+ V8EXPORT Local<String> StringValue() const;
+
+ static inline StringObject* Cast(v8::Value* obj);
+
+ private:
+ V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
* An instance of the built-in RegExp constructor (ECMA-262, 15.10).
*/
class RegExp : public Object {
@@ -2721,6 +2808,13 @@ class V8EXPORT StartupDataDecompressor { // NOLINT
char** raw_data;
};
+
+/**
+ * EntropySource is used as a callback function when v8 needs a source
+ * of entropy.
+ */
+typedef bool (*EntropySource)(unsigned char* buffer, size_t length);
+
/**
* Container class for static utility functions.
*/
@@ -2946,6 +3040,12 @@ class V8EXPORT V8 {
static bool Initialize();
/**
+ * Allows the host application to provide a callback which can be used
+ * as a source of entropy for random number generators.
+ */
+ static void SetEntropySource(EntropySource source);
+
+ /**
* Adjusts the amount of registered external memory. Used to give
* V8 an indication of the amount of externally allocated memory
* that is kept alive by JavaScript objects. V8 uses this to decide
@@ -4010,6 +4110,30 @@ Date* Date::Cast(v8::Value* value) {
}
+StringObject* StringObject::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<StringObject*>(value);
+}
+
+
+NumberObject* NumberObject::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<NumberObject*>(value);
+}
+
+
+BooleanObject* BooleanObject::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<BooleanObject*>(value);
+}
+
+
RegExp* RegExp::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
diff --git a/deps/v8/preparser/preparser-process.cc b/deps/v8/preparser/preparser-process.cc
index d7c96f0c7..e67851cbd 100644
--- a/deps/v8/preparser/preparser-process.cc
+++ b/deps/v8/preparser/preparser-process.cc
@@ -208,7 +208,7 @@ void fail(v8::PreParserData* data, const char* message, ...) {
fflush(stderr);
}
exit(EXIT_FAILURE);
-};
+}
bool IsFlag(const char* arg) {
diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc
index 7c30beccd..f37e731f3 100644
--- a/deps/v8/samples/shell.cc
+++ b/deps/v8/samples/shell.cc
@@ -95,6 +95,13 @@ class SourceGroup {
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;
diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript
index 6b3059aea..b45a5677a 100755
--- a/deps/v8/src/SConscript
+++ b/deps/v8/src/SConscript
@@ -243,7 +243,14 @@ PREPARSER_SOURCES = {
}
-D8_FILES = {
+D8_LIGHT_FILES = {
+ 'all': [
+ 'd8.cc'
+ ]
+}
+
+
+D8_FULL_FILES = {
'all': [
'd8.cc', 'd8-debug.cc'
],
@@ -323,11 +330,15 @@ def ConfigureObjectFiles():
# Build the standard platform-independent source files.
source_files = context.GetRelevantSources(SOURCES)
-
- d8_files = context.GetRelevantSources(D8_FILES)
d8_js = env.JS2C('d8-js.cc', 'd8.js', **{'TYPE': 'D8', 'COMPRESSION': 'off'})
d8_js_obj = context.ConfigureObject(env, d8_js, CPPPATH=['.'])
- d8_objs = [context.ConfigureObject(env, [d8_files]), d8_js_obj]
+ if context.options['library'] == 'shared':
+ d8_files = context.GetRelevantSources(D8_LIGHT_FILES)
+ d8_objs = []
+ else:
+ d8_files = context.GetRelevantSources(D8_FULL_FILES)
+ d8_objs = [d8_js_obj]
+ d8_objs.append(context.ConfigureObject(env, [d8_files]))
# Combine the JavaScript library files into a single C++ file and
# compile it.
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index dc1f90c0e..b0e977564 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -2167,6 +2167,65 @@ bool Value::IsDate() const {
}
+bool Value::IsStringObject() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::Value::IsStringObject()")) return false;
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ return obj->HasSpecificClassOf(isolate->heap()->String_symbol());
+}
+
+
+bool Value::IsNumberObject() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::Value::IsNumberObject()")) return false;
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ return obj->HasSpecificClassOf(isolate->heap()->Number_symbol());
+}
+
+
+static i::Object* LookupBuiltin(i::Isolate* isolate,
+ const char* builtin_name) {
+ i::Handle<i::String> symbol =
+ isolate->factory()->LookupAsciiSymbol(builtin_name);
+ i::Handle<i::JSBuiltinsObject> builtins = isolate->js_builtins_object();
+ return builtins->GetPropertyNoExceptionThrown(*symbol);
+}
+
+
+static bool CheckConstructor(i::Isolate* isolate,
+ i::Handle<i::JSObject> obj,
+ const char* class_name) {
+ return obj->map()->constructor() == LookupBuiltin(isolate, class_name);
+}
+
+
+bool Value::IsNativeError() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::Value::IsNativeError()")) return false;
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ if (obj->IsJSObject()) {
+ i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
+ return CheckConstructor(isolate, js_obj, "$Error") ||
+ CheckConstructor(isolate, js_obj, "$EvalError") ||
+ CheckConstructor(isolate, js_obj, "$RangeError") ||
+ CheckConstructor(isolate, js_obj, "$ReferenceError") ||
+ CheckConstructor(isolate, js_obj, "$SyntaxError") ||
+ CheckConstructor(isolate, js_obj, "$TypeError") ||
+ CheckConstructor(isolate, js_obj, "$URIError");
+ } else {
+ return false;
+ }
+}
+
+
+bool Value::IsBooleanObject() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::Value::IsBooleanObject()")) return false;
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ return obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol());
+}
+
+
bool Value::IsRegExp() const {
if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsRegExp()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
@@ -2362,6 +2421,36 @@ void v8::Date::CheckCast(v8::Value* that) {
}
+void v8::StringObject::CheckCast(v8::Value* that) {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::StringObject::Cast()")) return;
+ i::Handle<i::Object> obj = Utils::OpenHandle(that);
+ ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_symbol()),
+ "v8::StringObject::Cast()",
+ "Could not convert to StringObject");
+}
+
+
+void v8::NumberObject::CheckCast(v8::Value* that) {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::NumberObject::Cast()")) return;
+ i::Handle<i::Object> obj = Utils::OpenHandle(that);
+ ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_symbol()),
+ "v8::NumberObject::Cast()",
+ "Could not convert to NumberObject");
+}
+
+
+void v8::BooleanObject::CheckCast(v8::Value* that) {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::BooleanObject::Cast()")) return;
+ i::Handle<i::Object> obj = Utils::OpenHandle(that);
+ ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol()),
+ "v8::BooleanObject::Cast()",
+ "Could not convert to BooleanObject");
+}
+
+
void v8::RegExp::CheckCast(v8::Value* that) {
if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
@@ -2705,6 +2794,26 @@ Local<Value> v8::Object::Get(uint32_t index) {
}
+PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+ ON_BAILOUT(isolate, "v8::Object::GetPropertyAttribute()",
+ return static_cast<PropertyAttribute>(NONE));
+ ENTER_V8(isolate);
+ i::HandleScope scope(isolate);
+ i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+ i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+ if (!key_obj->IsString()) {
+ EXCEPTION_PREAMBLE(isolate);
+ key_obj = i::Execution::ToString(key_obj, &has_pending_exception);
+ EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
+ }
+ i::Handle<i::String> key_string = i::Handle<i::String>::cast(key_obj);
+ PropertyAttributes result = self->GetPropertyAttribute(*key_string);
+ if (result == ABSENT) return static_cast<PropertyAttribute>(NONE);
+ return static_cast<PropertyAttribute>(result);
+}
+
+
Local<Value> v8::Object::GetPrototype() {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::GetPrototype()",
@@ -3844,6 +3953,11 @@ bool v8::V8::Initialize() {
}
+void v8::V8::SetEntropySource(EntropySource source) {
+ i::V8::SetEntropySource(source);
+}
+
+
bool v8::V8::Dispose() {
i::Isolate* isolate = i::Isolate::Current();
if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
@@ -4427,6 +4541,73 @@ Local<v8::Object> v8::Object::New() {
}
+Local<v8::Value> v8::NumberObject::New(double value) {
+ i::Isolate* isolate = i::Isolate::Current();
+ EnsureInitializedForIsolate(isolate, "v8::NumberObject::New()");
+ LOG_API(isolate, "NumberObject::New");
+ ENTER_V8(isolate);
+ i::Handle<i::Object> number = isolate->factory()->NewNumber(value);
+ i::Handle<i::Object> obj = isolate->factory()->ToObject(number);
+ return Utils::ToLocal(obj);
+}
+
+
+double v8::NumberObject::NumberValue() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::NumberObject::NumberValue()")) return 0;
+ LOG_API(isolate, "NumberObject::NumberValue");
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ return jsvalue->value()->Number();
+}
+
+
+Local<v8::Value> v8::BooleanObject::New(bool value) {
+ i::Isolate* isolate = i::Isolate::Current();
+ EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
+ LOG_API(isolate, "BooleanObject::New");
+ ENTER_V8(isolate);
+ i::Handle<i::Object> boolean(value ? isolate->heap()->true_value()
+ : isolate->heap()->false_value());
+ i::Handle<i::Object> obj = isolate->factory()->ToObject(boolean);
+ return Utils::ToLocal(obj);
+}
+
+
+bool v8::BooleanObject::BooleanValue() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::BooleanObject::BooleanValue()")) return 0;
+ LOG_API(isolate, "BooleanObject::BooleanValue");
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ return jsvalue->value()->IsTrue();
+}
+
+
+Local<v8::Value> v8::StringObject::New(Handle<String> value) {
+ i::Isolate* isolate = i::Isolate::Current();
+ EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
+ LOG_API(isolate, "StringObject::New");
+ ENTER_V8(isolate);
+ i::Handle<i::Object> obj =
+ isolate->factory()->ToObject(Utils::OpenHandle(*value));
+ return Utils::ToLocal(obj);
+}
+
+
+Local<v8::String> v8::StringObject::StringValue() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::StringObject::StringValue()")) {
+ return Local<v8::String>();
+ }
+ LOG_API(isolate, "StringObject::StringValue");
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+ return Utils::ToLocal(
+ i::Handle<i::String>(i::String::cast(jsvalue->value())));
+}
+
+
Local<v8::Value> v8::Date::New(double time) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Date::New()");
diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc
index efa252dba..89df079f9 100644
--- a/deps/v8/src/arm/assembler-arm.cc
+++ b/deps/v8/src/arm/assembler-arm.cc
@@ -326,7 +326,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
no_const_pool_before_ = 0;
first_const_pool_use_ = -1;
last_bound_pos_ = 0;
- ast_id_for_reloc_info_ = kNoASTId;
+ ClearRecordedAstId();
}
@@ -2537,9 +2537,8 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
}
ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
- ASSERT(ast_id_for_reloc_info_ != kNoASTId);
- RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_);
- ast_id_for_reloc_info_ = kNoASTId;
+ RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId());
+ ClearRecordedAstId();
reloc_info_writer.Write(&reloc_info_with_ast_id);
} else {
reloc_info_writer.Write(&rinfo);
diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h
index fbf610a43..97d422650 100644
--- a/deps/v8/src/arm/assembler-arm.h
+++ b/deps/v8/src/arm/assembler-arm.h
@@ -1178,7 +1178,17 @@ class Assembler : public AssemblerBase {
// Record the AST id of the CallIC being compiled, so that it can be placed
// in the relocation information.
- void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; }
+ void SetRecordedAstId(unsigned ast_id) {
+ ASSERT(recorded_ast_id_ == kNoASTId);
+ recorded_ast_id_ = ast_id;
+ }
+
+ unsigned RecordedAstId() {
+ ASSERT(recorded_ast_id_ != kNoASTId);
+ return recorded_ast_id_;
+ }
+
+ void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
// Record a comment relocation entry that can be used by a disassembler.
// Use --code-comments to enable.
@@ -1244,7 +1254,7 @@ class Assembler : public AssemblerBase {
// Relocation for a type-recording IC has the AST id added to it. This
// member variable is a way to pass the information from the call site to
// the relocation info.
- unsigned ast_id_for_reloc_info_;
+ unsigned recorded_ast_id_;
bool emit_debug_code() const { return emit_debug_code_; }
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index ab7c6f247..eaad9f293 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -4722,6 +4722,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ mov(r0, Operand(argc_)); // Setup the number of arguments.
__ mov(r2, Operand(0, RelocInfo::NONE));
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+ __ SetCallKind(r5, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
}
diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc
index 22e7e4132..ea06064e5 100644
--- a/deps/v8/src/arm/lithium-arm.cc
+++ b/deps/v8/src/arm/lithium-arm.cc
@@ -372,6 +372,15 @@ void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
+void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+ elements()->PrintTo(stream);
+ stream->Add("[");
+ key()->PrintTo(stream);
+ stream->Add("] <- ");
+ value()->PrintTo(stream);
+}
+
+
void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add("[");
@@ -1844,6 +1853,18 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
}
+LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
+ HLoadKeyedFastDoubleElement* instr) {
+ ASSERT(instr->representation().IsDouble());
+ ASSERT(instr->key()->representation().IsInteger32());
+ LOperand* elements = UseTempRegister(instr->elements());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+ LLoadKeyedFastDoubleElement* result =
+ new LLoadKeyedFastDoubleElement(elements, key);
+ return AssignEnvironment(DefineAsRegister(result));
+}
+
+
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
@@ -1897,6 +1918,20 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
}
+LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
+ HStoreKeyedFastDoubleElement* instr) {
+ ASSERT(instr->value()->representation().IsDouble());
+ ASSERT(instr->elements()->representation().IsTagged());
+ ASSERT(instr->key()->representation().IsInteger32());
+
+ LOperand* elements = UseRegisterAtStart(instr->elements());
+ LOperand* val = UseTempRegister(instr->value());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+
+ return new LStoreKeyedFastDoubleElement(elements, key, val);
+}
+
+
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());
diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h
index ebeba8694..70c348de6 100644
--- a/deps/v8/src/arm/lithium-arm.h
+++ b/deps/v8/src/arm/lithium-arm.h
@@ -121,6 +121,7 @@ class LCodeGen;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
+ V(LoadKeyedFastDoubleElement) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
@@ -147,6 +148,7 @@ class LCodeGen;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
+ V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@@ -1137,6 +1139,22 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
+class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
+ inputs_[0] = elements;
+ inputs_[1] = key;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
+ "load-keyed-fast-double-element")
+ DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
+
+ LOperand* elements() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+};
+
+
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
@@ -1597,6 +1615,28 @@ class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
};
+class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+ LStoreKeyedFastDoubleElement(LOperand* elements,
+ LOperand* key,
+ LOperand* val) {
+ inputs_[0] = elements;
+ inputs_[1] = key;
+ inputs_[2] = val;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
+ "store-keyed-fast-double-element")
+ DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ LOperand* elements() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+ LOperand* value() { return inputs_[2]; }
+};
+
+
class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val) {
diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc
index dc93aea34..e4a14af7e 100644
--- a/deps/v8/src/arm/lithium-codegen-arm.cc
+++ b/deps/v8/src/arm/lithium-codegen-arm.cc
@@ -2433,6 +2433,48 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
}
+void LCodeGen::DoLoadKeyedFastDoubleElement(
+ LLoadKeyedFastDoubleElement* instr) {
+ Register elements = ToRegister(instr->elements());
+ bool key_is_constant = instr->key()->IsConstantOperand();
+ Register key = no_reg;
+ DwVfpRegister result = ToDoubleRegister(instr->result());
+ Register scratch = scratch0();
+
+ int shift_size =
+ ElementsKindToShiftSize(JSObject::FAST_DOUBLE_ELEMENTS);
+ int constant_key = 0;
+ if (key_is_constant) {
+ constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+ if (constant_key & 0xF0000000) {
+ Abort("array index constant value too big.");
+ }
+ } else {
+ key = ToRegister(instr->key());
+ }
+
+ Operand operand = key_is_constant
+ ? Operand(constant_key * (1 << shift_size) +
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag)
+ : Operand(key, LSL, shift_size);
+ __ add(elements, elements, operand);
+ if (!key_is_constant) {
+ __ add(elements, elements,
+ Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ }
+
+ if (instr->hydrogen()->RequiresHoleCheck()) {
+ // TODO(danno): If no hole check is required, there is no need to allocate
+ // elements into a temporary register, instead scratch can be used.
+ __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
+ __ cmp(scratch, Operand(kHoleNanUpper32));
+ DeoptimizeIf(eq, instr->environment());
+ }
+
+ __ vldr(result, elements, 0);
+}
+
+
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) {
Register external_pointer = ToRegister(instr->external_pointer());
@@ -2453,9 +2495,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
CpuFeatures::Scope scope(VFP3);
- DwVfpRegister result(ToDoubleRegister(instr->result()));
- Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
- : Operand(key, LSL, shift_size));
+ DwVfpRegister result = ToDoubleRegister(instr->result());
+ Operand operand = key_is_constant
+ ? Operand(constant_key * (1 << shift_size))
+ : Operand(key, LSL, shift_size);
__ add(scratch0(), external_pointer, operand);
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
__ vldr(result.low(), scratch0(), 0);
@@ -2464,7 +2507,7 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
__ vldr(result, scratch0(), 0);
}
} else {
- Register result(ToRegister(instr->result()));
+ Register result = ToRegister(instr->result());
MemOperand mem_operand(key_is_constant
? MemOperand(external_pointer, constant_key * (1 << shift_size))
: MemOperand(external_pointer, key, LSL, shift_size));
@@ -3243,6 +3286,48 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
}
+void LCodeGen::DoStoreKeyedFastDoubleElement(
+ LStoreKeyedFastDoubleElement* instr) {
+ DwVfpRegister value = ToDoubleRegister(instr->value());
+ Register elements = ToRegister(instr->elements());
+ Register key = no_reg;
+ Register scratch = scratch0();
+ bool key_is_constant = instr->key()->IsConstantOperand();
+ int constant_key = 0;
+ Label not_nan;
+
+ // Calculate the effective address of the slot in the array to store the
+ // double value.
+ if (key_is_constant) {
+ constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+ if (constant_key & 0xF0000000) {
+ Abort("array index constant value too big.");
+ }
+ } else {
+ key = ToRegister(instr->key());
+ }
+ int shift_size = ElementsKindToShiftSize(JSObject::FAST_DOUBLE_ELEMENTS);
+ Operand operand = key_is_constant
+ ? Operand(constant_key * (1 << shift_size) +
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag)
+ : Operand(key, LSL, shift_size);
+ __ add(scratch, elements, operand);
+ if (!key_is_constant) {
+ __ add(scratch, scratch,
+ Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ }
+
+ // Check for NaN. All NaNs must be canonicalized.
+ __ VFPCompareAndSetFlags(value, value);
+
+ // Only load canonical NaN if the comparison above set the overflow.
+ __ Vmov(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double(), vs);
+
+ __ bind(&not_nan);
+ __ vstr(value, scratch, 0);
+}
+
+
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) {
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index 320879a62..c34a57920 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -192,13 +192,13 @@ void MacroAssembler::Call(Handle<Code> code,
bind(&start);
ASSERT(RelocInfo::IsCodeTarget(rmode));
if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) {
- ASSERT(ast_id_for_reloc_info_ == kNoASTId);
- ast_id_for_reloc_info_ = ast_id;
+ SetRecordedAstId(ast_id);
rmode = RelocInfo::CODE_TARGET_WITH_ID;
}
// 'code' is always generated ARM code, never THUMB code
Call(reinterpret_cast<Address>(code.location()), rmode, cond);
- ASSERT_EQ(CallSize(code, rmode, cond), SizeOfCodeGeneratedSince(&start));
+ ASSERT_EQ(CallSize(code, rmode, ast_id, cond),
+ SizeOfCodeGeneratedSince(&start));
}
@@ -1862,7 +1862,7 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
- Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
+ Call(stub->GetCode(), RelocInfo::CODE_TARGET, kNoASTId, cond);
}
@@ -1872,7 +1872,8 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond) {
{ MaybeObject* maybe_result = stub->TryGetCode();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond);
+ Handle<Code> code(Code::cast(result));
+ Call(code, RelocInfo::CODE_TARGET, kNoASTId, cond);
return result;
}
@@ -2548,6 +2549,9 @@ void MacroAssembler::AssertFastElements(Register elements) {
LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
cmp(elements, ip);
b(eq, &ok);
+ LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
+ cmp(elements, ip);
+ b(eq, &ok);
LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
cmp(elements, ip);
b(eq, &ok);
diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc
index 86e49716d..c2665f885 100644
--- a/deps/v8/src/arm/stub-cache-arm.cc
+++ b/deps/v8/src/arm/stub-cache-arm.cc
@@ -4168,6 +4168,77 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+ MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- r0 : key
+ // -- r1 : receiver
+ // -----------------------------------
+ Label miss_force_generic, slow_allocate_heapnumber;
+
+ Register key_reg = r0;
+ Register receiver_reg = r1;
+ Register elements_reg = r2;
+ Register heap_number_reg = r2;
+ Register indexed_double_offset = r3;
+ Register scratch = r4;
+ Register scratch2 = r5;
+ Register scratch3 = r6;
+ Register heap_number_map = r7;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+ // Get the elements array.
+ __ ldr(elements_reg,
+ FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+ // Check that the key is within bounds.
+ __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+ __ cmp(key_reg, Operand(scratch));
+ __ b(hs, &miss_force_generic);
+
+ // Load the upper word of the double in the fixed array and test for NaN.
+ __ add(indexed_double_offset, elements_reg,
+ Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
+ uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
+ __ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
+ __ cmp(scratch, Operand(kHoleNanUpper32));
+ __ b(&miss_force_generic, eq);
+
+ // Non-NaN. Allocate a new heap number and copy the double value into it.
+ __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
+ heap_number_map, &slow_allocate_heapnumber);
+
+ // Don't need to reload the upper 32 bits of the double, it's already in
+ // scratch.
+ __ str(scratch, FieldMemOperand(heap_number_reg,
+ HeapNumber::kExponentOffset));
+ __ ldr(scratch, FieldMemOperand(indexed_double_offset,
+ FixedArray::kHeaderSize));
+ __ str(scratch, FieldMemOperand(heap_number_reg,
+ HeapNumber::kMantissaOffset));
+
+ __ mov(r0, heap_number_reg);
+ __ Ret();
+
+ __ bind(&slow_allocate_heapnumber);
+ Handle<Code> slow_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_Slow();
+ __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+
+ __ bind(&miss_force_generic);
+ Handle<Code> miss_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+ __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@@ -4231,6 +4302,125 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+ MacroAssembler* masm,
+ bool is_js_array) {
+ // ----------- S t a t e -------------
+ // -- r0 : value
+ // -- r1 : key
+ // -- r2 : receiver
+ // -- lr : return address
+ // -- r3 : scratch
+ // -- r4 : scratch
+ // -- r5 : scratch
+ // -----------------------------------
+ Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
+
+ Register value_reg = r0;
+ Register key_reg = r1;
+ Register receiver_reg = r2;
+ Register scratch = r3;
+ Register elements_reg = r4;
+ Register mantissa_reg = r5;
+ Register exponent_reg = r6;
+ Register scratch4 = r7;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+ __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+ __ ldr(elements_reg,
+ FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+ // Check that the key is within bounds.
+ if (is_js_array) {
+ __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+ } else {
+ __ ldr(scratch,
+ FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+ }
+ // Compare smis, unsigned compare catches both negative and out-of-bound
+ // indexes.
+ __ cmp(key_reg, scratch);
+ __ b(hs, &miss_force_generic);
+
+ // Handle smi values specially.
+ __ JumpIfSmi(value_reg, &smi_value);
+
+ // Ensure that the object is a heap number
+ __ CheckMap(value_reg,
+ scratch,
+ masm->isolate()->factory()->heap_number_map(),
+ &miss_force_generic,
+ DONT_DO_SMI_CHECK);
+
+ // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
+ // in the exponent.
+ __ mov(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
+ __ ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
+ __ cmp(exponent_reg, scratch);
+ __ b(ge, &maybe_nan);
+
+ __ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+
+ __ bind(&have_double_value);
+ __ add(scratch, elements_reg,
+ Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
+ __ str(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
+ uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+ __ str(exponent_reg, FieldMemOperand(scratch, offset));
+ __ Ret();
+
+ __ bind(&maybe_nan);
+ // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+ // it's an Infinity, and the non-NaN code path applies.
+ __ b(gt, &is_nan);
+ __ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+ __ cmp(mantissa_reg, Operand(0));
+ __ b(eq, &have_double_value);
+ __ bind(&is_nan);
+ // Load canonical NaN for storing into the double array.
+ uint64_t nan_int64 = BitCast<uint64_t>(
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double());
+ __ mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
+ __ mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
+ __ jmp(&have_double_value);
+
+ __ bind(&smi_value);
+ __ add(scratch, elements_reg,
+ Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ __ add(scratch, scratch,
+ Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
+ // scratch is now effective address of the double element
+
+ FloatingPointHelper::Destination destination;
+ if (CpuFeatures::IsSupported(VFP3)) {
+ destination = FloatingPointHelper::kVFPRegisters;
+ } else {
+ destination = FloatingPointHelper::kCoreRegisters;
+ }
+ __ SmiUntag(value_reg, value_reg);
+ FloatingPointHelper::ConvertIntToDouble(
+ masm, value_reg, destination,
+ d0, mantissa_reg, exponent_reg, // These are: double_dst, dst1, dst2.
+ scratch4, s2); // These are: scratch2, single_scratch.
+ if (destination == FloatingPointHelper::kVFPRegisters) {
+ CpuFeatures::Scope scope(VFP3);
+ __ vstr(d0, scratch, 0);
+ } else {
+ __ str(mantissa_reg, MemOperand(scratch, 0));
+ __ str(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
+ }
+ __ Ret();
+
+ // Handle store cache miss, replacing the ic with the generic stub.
+ __ bind(&miss_force_generic);
+ Handle<Code> ic =
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
#undef __
} } // namespace v8::internal
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index 60cf3f0c5..e6c13d954 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -999,7 +999,7 @@ function ArrayFilter(f, receiver) {
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
- var length = this.length;
+ var length = ToUint32(this.length);
var result = [];
var result_length = 0;
for (var i = 0; i < length; i++) {
@@ -1236,7 +1236,7 @@ function ArrayReduce(callback, current) {
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
- var length = this.length;
+ var length = ToUint32(this.length);
var i = 0;
find_initial: if (%_ArgumentsLength() < 2) {
@@ -1268,7 +1268,7 @@ function ArrayReduceRight(callback, current) {
if (!IS_FUNCTION(callback)) {
throw MakeTypeError('called_non_callable', [callback]);
}
- var i = this.length - 1;
+ var i = ToUint32(this.length) - 1;
find_initial: if (%_ArgumentsLength() < 2) {
for (; i >= 0; i--) {
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
index 3c7fc1c63..fbd808958 100644
--- a/deps/v8/src/assembler.cc
+++ b/deps/v8/src/assembler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// Copyright (c) 2011 Sun Microsystems Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,8 @@ const double DoubleConstant::one_half = 0.5;
const double DoubleConstant::minus_zero = -0.0;
const double DoubleConstant::uint8_max_value = 255;
const double DoubleConstant::zero = 0.0;
-const double DoubleConstant::nan = OS::nan_value();
+const double DoubleConstant::canonical_non_hole_nan = OS::nan_value();
+const double DoubleConstant::the_hole_nan = BitCast<double>(kHoleNanInt64);
const double DoubleConstant::negative_infinity = -V8_INFINITY;
const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
@@ -921,9 +922,15 @@ ExternalReference ExternalReference::address_of_negative_infinity() {
}
-ExternalReference ExternalReference::address_of_nan() {
+ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
return ExternalReference(reinterpret_cast<void*>(
- const_cast<double*>(&DoubleConstant::nan)));
+ const_cast<double*>(&DoubleConstant::canonical_non_hole_nan)));
+}
+
+
+ExternalReference ExternalReference::address_of_the_hole_nan() {
+ return ExternalReference(reinterpret_cast<void*>(
+ const_cast<double*>(&DoubleConstant::the_hole_nan)));
}
diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h
index bced11fec..2d14f0691 100644
--- a/deps/v8/src/assembler.h
+++ b/deps/v8/src/assembler.h
@@ -70,7 +70,8 @@ class DoubleConstant: public AllStatic {
static const double zero;
static const double uint8_max_value;
static const double negative_infinity;
- static const double nan;
+ static const double canonical_non_hole_nan;
+ static const double the_hole_nan;
};
@@ -629,7 +630,8 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference address_of_zero();
static ExternalReference address_of_uint8_max_value();
static ExternalReference address_of_negative_infinity();
- static ExternalReference address_of_nan();
+ static ExternalReference address_of_canonical_non_hole_nan();
+ static ExternalReference address_of_the_hole_nan();
static ExternalReference math_sin_double_function(Isolate* isolate);
static ExternalReference math_cos_double_function(Isolate* isolate);
diff --git a/deps/v8/src/ast-inl.h b/deps/v8/src/ast-inl.h
index c2bd61344..c750e6b03 100644
--- a/deps/v8/src/ast-inl.h
+++ b/deps/v8/src/ast-inl.h
@@ -37,68 +37,76 @@ namespace v8 {
namespace internal {
-SwitchStatement::SwitchStatement(ZoneStringList* labels)
- : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
+SwitchStatement::SwitchStatement(Isolate* isolate,
+ ZoneStringList* labels)
+ : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
tag_(NULL), cases_(NULL) {
}
-Block::Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
- : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
+Block::Block(Isolate* isolate,
+ ZoneStringList* labels,
+ int capacity,
+ bool is_initializer_block)
+ : BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY),
statements_(capacity),
is_initializer_block_(is_initializer_block) {
}
-BreakableStatement::BreakableStatement(ZoneStringList* labels, Type type)
+BreakableStatement::BreakableStatement(Isolate* isolate,
+ ZoneStringList* labels,
+ Type type)
: labels_(labels),
type_(type),
- entry_id_(GetNextId()),
- exit_id_(GetNextId()) {
+ entry_id_(GetNextId(isolate)),
+ exit_id_(GetNextId(isolate)) {
ASSERT(labels == NULL || labels->length() > 0);
}
-IterationStatement::IterationStatement(ZoneStringList* labels)
- : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
+IterationStatement::IterationStatement(Isolate* isolate, ZoneStringList* labels)
+ : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
body_(NULL),
continue_target_(),
- osr_entry_id_(GetNextId()) {
+ osr_entry_id_(GetNextId(isolate)) {
}
-DoWhileStatement::DoWhileStatement(ZoneStringList* labels)
- : IterationStatement(labels),
+DoWhileStatement::DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
cond_(NULL),
condition_position_(-1),
- continue_id_(GetNextId()),
- back_edge_id_(GetNextId()) {
+ continue_id_(GetNextId(isolate)),
+ back_edge_id_(GetNextId(isolate)) {
}
-WhileStatement::WhileStatement(ZoneStringList* labels)
- : IterationStatement(labels),
+WhileStatement::WhileStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
cond_(NULL),
may_have_function_literal_(true),
- body_id_(GetNextId()) {
+ body_id_(GetNextId(isolate)) {
}
-ForStatement::ForStatement(ZoneStringList* labels)
- : IterationStatement(labels),
+ForStatement::ForStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
init_(NULL),
cond_(NULL),
next_(NULL),
may_have_function_literal_(true),
loop_variable_(NULL),
- continue_id_(GetNextId()),
- body_id_(GetNextId()) {
+ continue_id_(GetNextId(isolate)),
+ body_id_(GetNextId(isolate)) {
}
-ForInStatement::ForInStatement(ZoneStringList* labels)
- : IterationStatement(labels), each_(NULL), enumerable_(NULL),
- assignment_id_(GetNextId()) {
+ForInStatement::ForInStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
+ each_(NULL),
+ enumerable_(NULL),
+ assignment_id_(GetNextId(isolate)) {
}
diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc
index 8b6cdcee9..2df62ee96 100644
--- a/deps/v8/src/ast.cc
+++ b/deps/v8/src/ast.cc
@@ -37,11 +37,11 @@ namespace v8 {
namespace internal {
AstSentinels::AstSentinels()
- : this_proxy_(true),
- identifier_proxy_(false),
- valid_left_hand_side_sentinel_(),
- this_property_(&this_proxy_, NULL, 0),
- call_sentinel_(NULL, NULL, 0) {
+ : this_proxy_(Isolate::Current(), true),
+ identifier_proxy_(Isolate::Current(), false),
+ valid_left_hand_side_sentinel_(Isolate::Current()),
+ this_property_(Isolate::Current(), &this_proxy_, NULL, 0),
+ call_sentinel_(Isolate::Current(), NULL, NULL, 0) {
}
@@ -72,8 +72,9 @@ CountOperation* ExpressionStatement::StatementAsCountOperation() {
}
-VariableProxy::VariableProxy(Variable* var)
- : name_(var->name()),
+VariableProxy::VariableProxy(Isolate* isolate, Variable* var)
+ : Expression(isolate),
+ name_(var->name()),
var_(NULL), // Will be set by the call to BindTo.
is_this_(var->is_this()),
inside_with_(false),
@@ -83,26 +84,29 @@ VariableProxy::VariableProxy(Variable* var)
}
-VariableProxy::VariableProxy(Handle<String> name,
+VariableProxy::VariableProxy(Isolate* isolate,
+ Handle<String> name,
bool is_this,
bool inside_with,
int position)
- : name_(name),
- var_(NULL),
- is_this_(is_this),
- inside_with_(inside_with),
- is_trivial_(false),
- position_(position) {
+ : Expression(isolate),
+ name_(name),
+ var_(NULL),
+ is_this_(is_this),
+ inside_with_(inside_with),
+ is_trivial_(false),
+ position_(position) {
// Names must be canonicalized for fast equality checks.
ASSERT(name->IsSymbol());
}
-VariableProxy::VariableProxy(bool is_this)
- : var_(NULL),
- is_this_(is_this),
- inside_with_(false),
- is_trivial_(false) {
+VariableProxy::VariableProxy(Isolate* isolate, bool is_this)
+ : Expression(isolate),
+ var_(NULL),
+ is_this_(is_this),
+ inside_with_(false),
+ is_trivial_(false) {
}
@@ -120,17 +124,19 @@ void VariableProxy::BindTo(Variable* var) {
}
-Assignment::Assignment(Token::Value op,
+Assignment::Assignment(Isolate* isolate,
+ Token::Value op,
Expression* target,
Expression* value,
int pos)
- : op_(op),
+ : Expression(isolate),
+ op_(op),
target_(target),
value_(value),
pos_(pos),
binary_operation_(NULL),
compound_load_id_(kNoNumber),
- assignment_id_(GetNextId()),
+ assignment_id_(GetNextId(isolate)),
block_start_(false),
block_end_(false),
is_monomorphic_(false),
@@ -138,8 +144,12 @@ Assignment::Assignment(Token::Value op,
ASSERT(Token::IsAssignmentOp(op));
if (is_compound()) {
binary_operation_ =
- new BinaryOperation(binary_op(), target, value, pos + 1);
- compound_load_id_ = GetNextId();
+ new(isolate->zone()) BinaryOperation(isolate,
+ binary_op(),
+ target,
+ value,
+ pos + 1);
+ compound_load_id_ = GetNextId(isolate);
}
}
@@ -186,8 +196,9 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
+ Isolate* isolate = Isolate::Current();
emit_store_ = true;
- key_ = new Literal(value->name());
+ key_ = new(isolate->zone()) Literal(isolate, value->name());
value_ = value;
kind_ = is_getter ? GETTER : SETTER;
}
@@ -1190,15 +1201,16 @@ RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
}
-CaseClause::CaseClause(Expression* label,
+CaseClause::CaseClause(Isolate* isolate,
+ Expression* label,
ZoneList<Statement*>* statements,
int pos)
: label_(label),
statements_(statements),
position_(pos),
compare_type_(NONE),
- compare_id_(AstNode::GetNextId()),
- entry_id_(AstNode::GetNextId()) {
+ compare_id_(AstNode::GetNextId(isolate)),
+ entry_id_(AstNode::GetNextId(isolate)) {
}
} } // namespace v8::internal
diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h
index 27d82cb34..23df48b8b 100644
--- a/deps/v8/src/ast.h
+++ b/deps/v8/src/ast.h
@@ -134,11 +134,15 @@ class AstNode: public ZoneObject {
static const int kNoNumber = -1;
static const int kFunctionEntryId = 2; // Using 0 could disguise errors.
- AstNode() {
- Isolate* isolate = Isolate::Current();
+ // Override ZoneObject's new to count allocated AST nodes.
+ void* operator new(size_t size, Zone* zone) {
+ Isolate* isolate = zone->isolate();
isolate->set_ast_node_count(isolate->ast_node_count() + 1);
+ return zone->New(static_cast<int>(size));
}
+ AstNode() {}
+
virtual ~AstNode() { }
virtual void Accept(AstVisitor* v) = 0;
@@ -165,14 +169,21 @@ class AstNode: public ZoneObject {
static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
protected:
- static unsigned GetNextId() { return ReserveIdRange(1); }
- static unsigned ReserveIdRange(int n) {
- Isolate* isolate = Isolate::Current();
+ static unsigned GetNextId(Isolate* isolate) {
+ return ReserveIdRange(isolate, 1);
+ }
+
+ static unsigned ReserveIdRange(Isolate* isolate, int n) {
unsigned tmp = isolate->ast_node_id();
isolate->set_ast_node_id(tmp + n);
return tmp;
}
+ private:
+ // Hidden to prevent accidental usage. It would have to load the
+ // current zone from the TLS.
+ void* operator new(size_t size);
+
friend class CaseClause; // Generates AST IDs.
};
@@ -210,7 +221,9 @@ class Expression: public AstNode {
kTest
};
- Expression() : id_(GetNextId()), test_id_(GetNextId()) {}
+ explicit Expression(Isolate* isolate)
+ : id_(GetNextId(isolate)),
+ test_id_(GetNextId(isolate)) {}
virtual int position() const {
UNREACHABLE();
@@ -277,6 +290,7 @@ class Expression: public AstNode {
*/
class ValidLeftHandSideSentinel: public Expression {
public:
+ explicit ValidLeftHandSideSentinel(Isolate* isolate) : Expression(isolate) {}
virtual bool IsValidLeftHandSide() { return true; }
virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
virtual bool IsInlineable() const;
@@ -308,7 +322,7 @@ class BreakableStatement: public Statement {
int ExitId() const { return exit_id_; }
protected:
- inline BreakableStatement(ZoneStringList* labels, Type type);
+ BreakableStatement(Isolate* isolate, ZoneStringList* labels, Type type);
private:
ZoneStringList* labels_;
@@ -321,7 +335,10 @@ class BreakableStatement: public Statement {
class Block: public BreakableStatement {
public:
- inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block);
+ inline Block(Isolate* isolate,
+ ZoneStringList* labels,
+ int capacity,
+ bool is_initializer_block);
DECLARE_NODE_TYPE(Block)
@@ -389,7 +406,7 @@ class IterationStatement: public BreakableStatement {
Label* continue_target() { return &continue_target_; }
protected:
- explicit inline IterationStatement(ZoneStringList* labels);
+ inline IterationStatement(Isolate* isolate, ZoneStringList* labels);
void Initialize(Statement* body) {
body_ = body;
@@ -404,7 +421,7 @@ class IterationStatement: public BreakableStatement {
class DoWhileStatement: public IterationStatement {
public:
- explicit inline DoWhileStatement(ZoneStringList* labels);
+ inline DoWhileStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(DoWhileStatement)
@@ -437,7 +454,7 @@ class DoWhileStatement: public IterationStatement {
class WhileStatement: public IterationStatement {
public:
- explicit inline WhileStatement(ZoneStringList* labels);
+ inline WhileStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(WhileStatement)
@@ -470,7 +487,7 @@ class WhileStatement: public IterationStatement {
class ForStatement: public IterationStatement {
public:
- explicit inline ForStatement(ZoneStringList* labels);
+ inline ForStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(ForStatement)
@@ -519,7 +536,7 @@ class ForStatement: public IterationStatement {
class ForInStatement: public IterationStatement {
public:
- explicit inline ForInStatement(ZoneStringList* labels);
+ inline ForInStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(ForInStatement)
@@ -636,7 +653,10 @@ class ExitContextStatement: public Statement {
class CaseClause: public ZoneObject {
public:
- CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
+ CaseClause(Isolate* isolate,
+ Expression* label,
+ ZoneList<Statement*>* statements,
+ int pos);
bool is_default() const { return label_ == NULL; }
Expression* label() const {
@@ -671,7 +691,7 @@ class CaseClause: public ZoneObject {
class SwitchStatement: public BreakableStatement {
public:
- explicit inline SwitchStatement(ZoneStringList* labels);
+ inline SwitchStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(SwitchStatement)
@@ -697,15 +717,16 @@ class SwitchStatement: public BreakableStatement {
// given if-statement has a then- or an else-part containing code.
class IfStatement: public Statement {
public:
- IfStatement(Expression* condition,
+ IfStatement(Isolate* isolate,
+ Expression* condition,
Statement* then_statement,
Statement* else_statement)
: condition_(condition),
then_statement_(then_statement),
else_statement_(else_statement),
- if_id_(GetNextId()),
- then_id_(GetNextId()),
- else_id_(GetNextId()) {
+ if_id_(GetNextId(isolate)),
+ then_id_(GetNextId(isolate)),
+ else_id_(GetNextId(isolate)) {
}
DECLARE_NODE_TYPE(IfStatement)
@@ -834,7 +855,8 @@ class EmptyStatement: public Statement {
class Literal: public Expression {
public:
- explicit Literal(Handle<Object> handle) : handle_(handle) { }
+ Literal(Isolate* isolate, Handle<Object> handle)
+ : Expression(isolate), handle_(handle) { }
DECLARE_NODE_TYPE(Literal)
@@ -887,8 +909,14 @@ class Literal: public Expression {
// Base class for literals that needs space in the corresponding JSFunction.
class MaterializedLiteral: public Expression {
public:
- explicit MaterializedLiteral(int literal_index, bool is_simple, int depth)
- : literal_index_(literal_index), is_simple_(is_simple), depth_(depth) {}
+ MaterializedLiteral(Isolate* isolate,
+ int literal_index,
+ bool is_simple,
+ int depth)
+ : Expression(isolate),
+ literal_index_(literal_index),
+ is_simple_(is_simple),
+ depth_(depth) {}
virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
@@ -944,14 +972,15 @@ class ObjectLiteral: public MaterializedLiteral {
bool emit_store_;
};
- ObjectLiteral(Handle<FixedArray> constant_properties,
+ ObjectLiteral(Isolate* isolate,
+ Handle<FixedArray> constant_properties,
ZoneList<Property*>* properties,
int literal_index,
bool is_simple,
bool fast_elements,
int depth,
bool has_function)
- : MaterializedLiteral(literal_index, is_simple, depth),
+ : MaterializedLiteral(isolate, literal_index, is_simple, depth),
constant_properties_(constant_properties),
properties_(properties),
fast_elements_(fast_elements),
@@ -990,10 +1019,11 @@ class ObjectLiteral: public MaterializedLiteral {
// Node for capturing a regexp literal.
class RegExpLiteral: public MaterializedLiteral {
public:
- RegExpLiteral(Handle<String> pattern,
+ RegExpLiteral(Isolate* isolate,
+ Handle<String> pattern,
Handle<String> flags,
int literal_index)
- : MaterializedLiteral(literal_index, false, 1),
+ : MaterializedLiteral(isolate, literal_index, false, 1),
pattern_(pattern),
flags_(flags) {}
@@ -1011,15 +1041,16 @@ class RegExpLiteral: public MaterializedLiteral {
// for minimizing the work when constructing it at runtime.
class ArrayLiteral: public MaterializedLiteral {
public:
- ArrayLiteral(Handle<FixedArray> constant_elements,
+ ArrayLiteral(Isolate* isolate,
+ Handle<FixedArray> constant_elements,
ZoneList<Expression*>* values,
int literal_index,
bool is_simple,
int depth)
- : MaterializedLiteral(literal_index, is_simple, depth),
+ : MaterializedLiteral(isolate, literal_index, is_simple, depth),
constant_elements_(constant_elements),
values_(values),
- first_element_id_(ReserveIdRange(values->length())) {}
+ first_element_id_(ReserveIdRange(isolate, values->length())) {}
DECLARE_NODE_TYPE(ArrayLiteral)
@@ -1038,7 +1069,7 @@ class ArrayLiteral: public MaterializedLiteral {
class VariableProxy: public Expression {
public:
- explicit VariableProxy(Variable* var);
+ VariableProxy(Isolate* isolate, Variable* var);
DECLARE_NODE_TYPE(VariableProxy)
@@ -1085,11 +1116,12 @@ class VariableProxy: public Expression {
bool is_trivial_;
int position_;
- VariableProxy(Handle<String> name,
+ VariableProxy(Isolate* isolate,
+ Handle<String> name,
bool is_this,
bool inside_with,
int position = RelocInfo::kNoPosition);
- explicit VariableProxy(bool is_this);
+ VariableProxy(Isolate* isolate, bool is_this);
friend class Scope;
};
@@ -1100,7 +1132,8 @@ class VariableProxySentinel: public VariableProxy {
virtual bool IsValidLeftHandSide() { return !is_this(); }
private:
- explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
+ VariableProxySentinel(Isolate* isolate, bool is_this)
+ : VariableProxy(isolate, is_this) { }
friend class AstSentinels;
};
@@ -1130,8 +1163,8 @@ class Slot: public Expression {
LOOKUP
};
- Slot(Variable* var, Type type, int index)
- : var_(var), type_(type), index_(index) {
+ Slot(Isolate* isolate, Variable* var, Type type, int index)
+ : Expression(isolate), var_(var), type_(type), index_(index) {
ASSERT(var != NULL);
}
@@ -1162,8 +1195,13 @@ class Property: public Expression {
// properties should use the global object as receiver, not the base object
// of the resolved Reference.
enum Type { NORMAL, SYNTHETIC };
- Property(Expression* obj, Expression* key, int pos, Type type = NORMAL)
- : obj_(obj),
+ Property(Isolate* isolate,
+ Expression* obj,
+ Expression* key,
+ int pos,
+ Type type = NORMAL)
+ : Expression(isolate),
+ obj_(obj),
key_(key),
pos_(pos),
type_(type),
@@ -1215,14 +1253,18 @@ class Property: public Expression {
class Call: public Expression {
public:
- Call(Expression* expression, ZoneList<Expression*>* arguments, int pos)
- : expression_(expression),
+ Call(Isolate* isolate,
+ Expression* expression,
+ ZoneList<Expression*>* arguments,
+ int pos)
+ : Expression(isolate),
+ expression_(expression),
arguments_(arguments),
pos_(pos),
is_monomorphic_(false),
check_type_(RECEIVER_MAP_CHECK),
receiver_types_(NULL),
- return_id_(GetNextId()) {
+ return_id_(GetNextId(isolate)) {
}
DECLARE_NODE_TYPE(Call)
@@ -1301,8 +1343,14 @@ class AstSentinels {
class CallNew: public Expression {
public:
- CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
- : expression_(expression), arguments_(arguments), pos_(pos) { }
+ CallNew(Isolate* isolate,
+ Expression* expression,
+ ZoneList<Expression*>* arguments,
+ int pos)
+ : Expression(isolate),
+ expression_(expression),
+ arguments_(arguments),
+ pos_(pos) { }
DECLARE_NODE_TYPE(CallNew)
@@ -1325,10 +1373,14 @@ class CallNew: public Expression {
// implemented in JavaScript (see "v8natives.js").
class CallRuntime: public Expression {
public:
- CallRuntime(Handle<String> name,
+ CallRuntime(Isolate* isolate,
+ Handle<String> name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments)
- : name_(name), function_(function), arguments_(arguments) { }
+ : Expression(isolate),
+ name_(name),
+ function_(function),
+ arguments_(arguments) { }
DECLARE_NODE_TYPE(CallRuntime)
@@ -1348,8 +1400,11 @@ class CallRuntime: public Expression {
class UnaryOperation: public Expression {
public:
- UnaryOperation(Token::Value op, Expression* expression, int pos)
- : op_(op), expression_(expression), pos_(pos) {
+ UnaryOperation(Isolate* isolate,
+ Token::Value op,
+ Expression* expression,
+ int pos)
+ : Expression(isolate), op_(op), expression_(expression), pos_(pos) {
ASSERT(Token::IsUnaryOp(op));
}
@@ -1372,14 +1427,15 @@ class UnaryOperation: public Expression {
class BinaryOperation: public Expression {
public:
- BinaryOperation(Token::Value op,
+ BinaryOperation(Isolate* isolate,
+ Token::Value op,
Expression* left,
Expression* right,
int pos)
- : op_(op), left_(left), right_(right), pos_(pos) {
+ : Expression(isolate), op_(op), left_(left), right_(right), pos_(pos) {
ASSERT(Token::IsBinaryOp(op));
right_id_ = (op == Token::AND || op == Token::OR)
- ? static_cast<int>(GetNextId())
+ ? static_cast<int>(GetNextId(isolate))
: AstNode::kNoNumber;
}
@@ -1410,13 +1466,18 @@ class BinaryOperation: public Expression {
class CountOperation: public Expression {
public:
- CountOperation(Token::Value op, bool is_prefix, Expression* expr, int pos)
- : op_(op),
+ CountOperation(Isolate* isolate,
+ Token::Value op,
+ bool is_prefix,
+ Expression* expr,
+ int pos)
+ : Expression(isolate),
+ op_(op),
is_prefix_(is_prefix),
expression_(expr),
pos_(pos),
- assignment_id_(GetNextId()),
- count_id_(GetNextId()),
+ assignment_id_(GetNextId(isolate)),
+ count_id_(GetNextId(isolate)),
receiver_types_(NULL) { }
DECLARE_NODE_TYPE(CountOperation)
@@ -1462,11 +1523,17 @@ class CountOperation: public Expression {
class CompareOperation: public Expression {
public:
- CompareOperation(Token::Value op,
+ CompareOperation(Isolate* isolate,
+ Token::Value op,
Expression* left,
Expression* right,
int pos)
- : op_(op), left_(left), right_(right), pos_(pos), compare_type_(NONE) {
+ : Expression(isolate),
+ op_(op),
+ left_(left),
+ right_(right),
+ pos_(pos),
+ compare_type_(NONE) {
ASSERT(Token::IsCompareOp(op));
}
@@ -1501,8 +1568,8 @@ class CompareOperation: public Expression {
class CompareToNull: public Expression {
public:
- CompareToNull(bool is_strict, Expression* expression)
- : is_strict_(is_strict), expression_(expression) { }
+ CompareToNull(Isolate* isolate, bool is_strict, Expression* expression)
+ : Expression(isolate), is_strict_(is_strict), expression_(expression) { }
DECLARE_NODE_TYPE(CompareToNull)
@@ -1520,18 +1587,20 @@ class CompareToNull: public Expression {
class Conditional: public Expression {
public:
- Conditional(Expression* condition,
+ Conditional(Isolate* isolate,
+ Expression* condition,
Expression* then_expression,
Expression* else_expression,
int then_expression_position,
int else_expression_position)
- : condition_(condition),
+ : Expression(isolate),
+ condition_(condition),
then_expression_(then_expression),
else_expression_(else_expression),
then_expression_position_(then_expression_position),
else_expression_position_(else_expression_position),
- then_id_(GetNextId()),
- else_id_(GetNextId()) {
+ then_id_(GetNextId(isolate)),
+ else_id_(GetNextId(isolate)) {
}
DECLARE_NODE_TYPE(Conditional)
@@ -1561,7 +1630,11 @@ class Conditional: public Expression {
class Assignment: public Expression {
public:
- Assignment(Token::Value op, Expression* target, Expression* value, int pos);
+ Assignment(Isolate* isolate,
+ Token::Value op,
+ Expression* target,
+ Expression* value,
+ int pos);
DECLARE_NODE_TYPE(Assignment)
@@ -1621,8 +1694,8 @@ class Assignment: public Expression {
class Throw: public Expression {
public:
- Throw(Expression* exception, int pos)
- : exception_(exception), pos_(pos) {}
+ Throw(Isolate* isolate, Expression* exception, int pos)
+ : Expression(isolate), exception_(exception), pos_(pos) {}
DECLARE_NODE_TYPE(Throw)
@@ -1638,7 +1711,8 @@ class Throw: public Expression {
class FunctionLiteral: public Expression {
public:
- FunctionLiteral(Handle<String> name,
+ FunctionLiteral(Isolate* isolate,
+ Handle<String> name,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
@@ -1650,7 +1724,8 @@ class FunctionLiteral: public Expression {
int end_position,
bool is_expression,
bool has_duplicate_parameters)
- : name_(name),
+ : Expression(isolate),
+ name_(name),
scope_(scope),
body_(body),
materialized_literal_count_(materialized_literal_count),
@@ -1729,9 +1804,10 @@ class FunctionLiteral: public Expression {
class SharedFunctionInfoLiteral: public Expression {
public:
- explicit SharedFunctionInfoLiteral(
+ SharedFunctionInfoLiteral(
+ Isolate* isolate,
Handle<SharedFunctionInfo> shared_function_info)
- : shared_function_info_(shared_function_info) { }
+ : Expression(isolate), shared_function_info_(shared_function_info) { }
DECLARE_NODE_TYPE(SharedFunctionInfoLiteral)
@@ -1747,6 +1823,7 @@ class SharedFunctionInfoLiteral: public Expression {
class ThisFunction: public Expression {
public:
+ explicit ThisFunction(Isolate* isolate) : Expression(isolate) {}
DECLARE_NODE_TYPE(ThisFunction)
virtual bool IsInlineable() const;
};
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc
index 8e34b9cf5..8cca5614b 100644
--- a/deps/v8/src/bootstrapper.cc
+++ b/deps/v8/src/bootstrapper.cc
@@ -1309,6 +1309,7 @@ void Genesis::InstallNativeFunctions() {
void Genesis::InstallExperimentalNativeFunctions() {
if (FLAG_harmony_proxies) {
+ INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap);
INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap);
INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap);
}
diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc
index 6a44d8cae..d403a951c 100644
--- a/deps/v8/src/builtins.cc
+++ b/deps/v8/src/builtins.cc
@@ -1202,10 +1202,10 @@ MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
ASSERT(!CalledAsConstructor(isolate));
Heap* heap = isolate->heap();
- Handle<Object> receiver = args.at<Object>(0);
+ Handle<Object> receiver = args.receiver();
// Get the object called.
- JSObject* obj = JSObject::cast(*args.receiver());
+ JSObject* obj = JSObject::cast(*receiver);
// Get the invocation callback from the function descriptor that was
// used to create the called object.
diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc
index 5c0ef5a4a..1d1128f2d 100644
--- a/deps/v8/src/code-stubs.cc
+++ b/deps/v8/src/code-stubs.cc
@@ -250,7 +250,7 @@ void KeyedLoadElementStub::Generate(MacroAssembler* masm) {
KeyedLoadStubCompiler::GenerateLoadFastElement(masm);
break;
case JSObject::FAST_DOUBLE_ELEMENTS:
- UNIMPLEMENTED();
+ KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(masm);
break;
case JSObject::EXTERNAL_BYTE_ELEMENTS:
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
@@ -279,7 +279,8 @@ void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
KeyedStoreStubCompiler::GenerateStoreFastElement(masm, is_js_array_);
break;
case JSObject::FAST_DOUBLE_ELEMENTS:
- UNIMPLEMENTED();
+ KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
+ is_js_array_);
break;
case JSObject::EXTERNAL_BYTE_ELEMENTS:
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index e09b72f7d..c265b95ac 100755
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -511,7 +511,6 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
info.SetPreParseData(pre_data);
if (natives == NATIVES_CODE) {
info.MarkAsAllowingNativesSyntax();
- info.MarkAsNative();
}
result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null()) {
@@ -679,7 +678,6 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
info.SetFunction(literal);
info.SetScope(literal->scope());
if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
- if (script->type()->value() == Script::TYPE_NATIVE) info.MarkAsNative();
LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
// Determine if the function can be lazily compiled. This is necessary to
diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h
index a77fc8ea4..8e92cf5a1 100644
--- a/deps/v8/src/compiler.h
+++ b/deps/v8/src/compiler.h
@@ -173,9 +173,12 @@ class CompilationInfo BASE_EMBEDDED {
void Initialize(Mode mode) {
mode_ = V8::UseCrankshaft() ? mode : NONOPT;
- if (!shared_info_.is_null()) {
- if (shared_info_->strict_mode()) MarkAsStrictMode();
- if (shared_info_->native()) MarkAsNative();
+ ASSERT(!script_.is_null());
+ if (script_->type()->value() == Script::TYPE_NATIVE) {
+ MarkAsNative();
+ }
+ if (!shared_info_.is_null() && shared_info_->strict_mode()) {
+ MarkAsStrictMode();
}
}
diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h
index 0f3d44cc2..53b40f127 100644
--- a/deps/v8/src/contexts.h
+++ b/deps/v8/src/contexts.h
@@ -110,6 +110,7 @@ enum ContextLookupFlags {
V(MAP_CACHE_INDEX, Object, map_cache) \
V(CONTEXT_DATA_INDEX, Object, data) \
V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
+ V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \
V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap)
@@ -227,6 +228,7 @@ class Context: public FixedArray {
OUT_OF_MEMORY_INDEX,
CONTEXT_DATA_INDEX,
ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
+ DERIVED_HAS_TRAP_INDEX,
DERIVED_GET_TRAP_INDEX,
DERIVED_SET_TRAP_INDEX,
diff --git a/deps/v8/src/conversions-inl.h b/deps/v8/src/conversions-inl.h
index f1f526ffc..b82863856 100644
--- a/deps/v8/src/conversions-inl.h
+++ b/deps/v8/src/conversions-inl.h
@@ -454,7 +454,6 @@ static double InternalStringToDouble(UnicodeCache* unicode_cache,
int significant_digits = 0;
int insignificant_digits = 0;
bool nonzero_digit_dropped = false;
- bool fractional_part = false;
bool negative = false;
@@ -557,10 +556,8 @@ static double InternalStringToDouble(UnicodeCache* unicode_cache,
}
}
- // We don't emit a '.', but adjust the exponent instead.
- fractional_part = true;
-
- // There is a fractional part.
+ // There is a fractional part. We don't emit a '.', but adjust the exponent
+ // instead.
while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) {
ASSERT(buffer_pos < kBufferSize);
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc
index 5f5735009..4917f7d64 100644
--- a/deps/v8/src/d8.cc
+++ b/deps/v8/src/d8.cc
@@ -26,33 +26,49 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef V8_SHARED
+#define USING_V8_SHARED
+#endif
+
#ifdef COMPRESS_STARTUP_DATA_BZ2
#include <bzlib.h>
#endif
+
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
-#include "v8.h"
+#ifdef USING_V8_SHARED
+#include <assert.h>
+#include "../include/v8-testing.h"
+#endif // USING_V8_SHARED
#include "d8.h"
+
+#ifndef USING_V8_SHARED
+#include "api.h"
+#include "checks.h"
#include "d8-debug.h"
#include "debug.h"
-#include "api.h"
#include "natives.h"
#include "platform.h"
+#include "v8.h"
+#endif // USING_V8_SHARED
#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h> // NOLINT
#endif
-namespace v8 {
-
+#ifdef USING_V8_SHARED
+#define ASSERT(condition) assert(condition)
+#endif // USING_V8_SHARED
-const char* Shell::kHistoryFileName = ".d8_history";
-const char* Shell::kPrompt = "d8> ";
+namespace v8 {
+#ifndef USING_V8_SHARED
LineEditor *LineEditor::first_ = NULL;
+const char* Shell::kHistoryFileName = ".d8_history";
LineEditor::LineEditor(Type type, const char* name)
@@ -98,17 +114,22 @@ CounterMap* Shell::counter_map_;
i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ = &local_counters_;
+i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
Persistent<Context> Shell::utility_context_;
+#endif // USING_V8_SHARED
+
Persistent<Context> Shell::evaluation_context_;
-i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
ShellOptions Shell::options;
+const char* Shell::kPrompt = "d8> ";
+#ifndef USING_V8_SHARED
bool CounterMap::Match(void* key1, void* key2) {
const char* name1 = reinterpret_cast<const char*>(key1);
const char* name2 = reinterpret_cast<const char*>(key2);
return strcmp(name1, name2) == 0;
}
+#endif // USING_V8_SHARED
// Converts a V8 value to a C string.
@@ -122,17 +143,22 @@ bool Shell::ExecuteString(Handle<String> source,
Handle<Value> name,
bool print_result,
bool report_exceptions) {
+#ifndef USING_V8_SHARED
+ bool FLAG_debugger = i::FLAG_debugger;
+#else
+ bool FLAG_debugger = false;
+#endif // USING_V8_SHARED
HandleScope handle_scope;
TryCatch try_catch;
options.script_executed = true;
- if (i::FLAG_debugger) {
+ if (FLAG_debugger) {
// When debugging make exceptions appear to be uncaught.
try_catch.SetVerbose(true);
}
Handle<Script> script = Script::Compile(source, name);
if (script.IsEmpty()) {
// Print errors that happened during compilation.
- if (report_exceptions && !i::FLAG_debugger)
+ if (report_exceptions && !FLAG_debugger)
ReportException(&try_catch);
return false;
} else {
@@ -140,7 +166,7 @@ bool Shell::ExecuteString(Handle<String> source,
if (result.IsEmpty()) {
ASSERT(try_catch.HasCaught());
// Print errors that happened during execution.
- if (report_exceptions && !i::FLAG_debugger)
+ if (report_exceptions && !FLAG_debugger)
ReportException(&try_catch);
return false;
} else {
@@ -161,6 +187,7 @@ bool Shell::ExecuteString(Handle<String> source,
Handle<Value> Shell::Print(const Arguments& args) {
Handle<Value> val = Write(args);
printf("\n");
+ fflush(stdout);
return val;
}
@@ -196,15 +223,20 @@ Handle<Value> Shell::Read(const Arguments& args) {
Handle<Value> Shell::ReadLine(const Arguments& args) {
- i::SmartPointer<char> line(i::ReadLine(""));
- if (*line == NULL) {
- return Null();
- }
- size_t len = strlen(*line);
- if (len > 0 && line[len - 1] == '\n') {
- --len;
- }
- return String::New(*line, len);
+ static const int kBufferSize = 256;
+ char buffer[kBufferSize];
+ Handle<String> accumulator = String::New("");
+ bool linebreak;
+ int length;
+ do { // Repeat if the line ends with an escape '\'.
+ // fgets got an error. Just give up.
+ if (fgets(buffer, kBufferSize, stdin) == NULL) return Null();
+ length = strlen(buffer);
+ linebreak = (length > 1 && buffer[length-2] == '\\');
+ if (linebreak) buffer[length-2] = '\n';
+ accumulator = String::Concat(accumulator, String::New(buffer, length-1));
+ } while (linebreak);
+ return accumulator;
}
@@ -236,6 +268,10 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args,
return ThrowException(
String::New("Array constructor needs one parameter."));
}
+ static const int kMaxLength = 0x3fffffff;
+#ifndef USING_V8_SHARED
+ ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
+#endif // USING_V8_SHARED
size_t length = 0;
if (args[0]->IsUint32()) {
length = args[0]->Uint32Value();
@@ -244,7 +280,7 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args,
if (raw_length < 0) {
return ThrowException(String::New("Array length must not be negative."));
}
- if (raw_length > i::ExternalArray::kMaxLength) {
+ if (raw_length > kMaxLength) {
return ThrowException(
String::New("Array length exceeds maximum length."));
}
@@ -252,7 +288,7 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args,
} else {
return ThrowException(String::New("Array length must be a number."));
}
- if (length > static_cast<size_t>(i::ExternalArray::kMaxLength)) {
+ if (length > static_cast<size_t>(kMaxLength)) {
return ThrowException(String::New("Array length exceeds maximum length."));
}
void* data = calloc(length, element_size);
@@ -332,7 +368,9 @@ Handle<Value> Shell::Yield(const Arguments& args) {
Handle<Value> Shell::Quit(const Arguments& args) {
int exit_code = args[0]->Int32Value();
+#ifndef USING_V8_SHARED
OnExit();
+#endif // USING_V8_SHARED
exit(exit_code);
return Undefined();
}
@@ -381,6 +419,7 @@ void Shell::ReportException(v8::TryCatch* try_catch) {
}
+#ifndef USING_V8_SHARED
Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
HandleScope handle_scope;
Context::Scope context_scope(utility_context_);
@@ -414,9 +453,11 @@ Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
return val;
}
-#endif
+#endif // ENABLE_DEBUGGER_SUPPORT
+#endif // USING_V8_SHARED
+#ifndef USING_V8_SHARED
int32_t* Counter::Bind(const char* name, bool is_histogram) {
int i;
for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@@ -448,8 +489,8 @@ Counter* CounterCollection::GetNextCounter() {
void Shell::MapCounters(const char* name) {
- counters_file_ = i::OS::MemoryMappedFile::create(name,
- sizeof(CounterCollection), &local_counters_);
+ counters_file_ = i::OS::MemoryMappedFile::create(
+ name, sizeof(CounterCollection), &local_counters_);
void* memory = (counters_file_ == NULL) ?
NULL : counters_file_->memory();
if (memory == NULL) {
@@ -514,6 +555,7 @@ void Shell::AddHistogramSample(void* histogram, int sample) {
counter->AddSample(sample);
}
+
void Shell::InstallUtilityScript() {
Locker lock;
HandleScope scope;
@@ -532,7 +574,7 @@ void Shell::InstallUtilityScript() {
utility_context_->Global()->Set(String::New("$debug"),
Utils::ToLocal(js_debug));
debug->debug_context()->set_security_token(HEAP->undefined_value());
-#endif
+#endif // ENABLE_DEBUGGER_SUPPORT
// Run the d8 shell utility script in the utility context
int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
@@ -550,10 +592,10 @@ void Shell::InstallUtilityScript() {
// in the debugger.
i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
- ? i::Handle<i::Script>(i::Script::cast(
- i::JSFunction::cast(*compiled_script)->shared()->script()))
- : i::Handle<i::Script>(i::Script::cast(
- i::SharedFunctionInfo::cast(*compiled_script)->script()));
+ ? i::Handle<i::Script>(i::Script::cast(
+ i::JSFunction::cast(*compiled_script)->shared()->script()))
+ : i::Handle<i::Script>(i::Script::cast(
+ i::SharedFunctionInfo::cast(*compiled_script)->script()));
script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
#ifdef ENABLE_DEBUGGER_SUPPORT
@@ -561,8 +603,9 @@ void Shell::InstallUtilityScript() {
if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
v8::Debug::SetDebugEventListener(HandleDebugEvent);
}
-#endif
+#endif // ENABLE_DEBUGGER_SUPPORT
}
+#endif // USING_V8_SHARED
#ifdef COMPRESS_STARTUP_DATA_BZ2
@@ -629,9 +672,11 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
#endif
+#ifndef USING_V8_SHARED
Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
AddOSMethods(os_templ);
global_template->Set(String::New("os"), os_templ);
+#endif // USING_V8_SHARED
return global_template;
}
@@ -647,6 +692,7 @@ void Shell::Initialize() {
}
#endif
+#ifndef USING_V8_SHARED
Shell::counter_map_ = new CounterMap();
// Set up counters
if (i::StrLength(i::FLAG_map_counters) != 0)
@@ -656,9 +702,10 @@ void Shell::Initialize() {
V8::SetCreateHistogramFunction(CreateHistogram);
V8::SetAddHistogramSampleFunction(AddHistogramSample);
}
-
+#endif // USING_V8_SHARED
if (options.test_shell) return;
+#ifndef USING_V8_SHARED
Locker lock;
HandleScope scope;
Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
@@ -669,18 +716,22 @@ void Shell::Initialize() {
if (i::FLAG_debugger_agent) {
v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
}
-#endif
+#endif // ENABLE_DEBUGGER_SUPPORT
+#endif // USING_V8_SHARED
}
Persistent<Context> Shell::CreateEvaluationContext() {
+#ifndef USING_V8_SHARED
// This needs to be a critical section since this is not thread-safe
i::ScopedLock lock(context_mutex_);
+#endif // USING_V8_SHARED
// Initialize the global objects
Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
Persistent<Context> context = Context::New(NULL, global_template);
Context::Scope scope(context);
+#ifndef USING_V8_SHARED
i::JSArguments js_args = i::FLAG_js_arguments;
i::Handle<i::FixedArray> arguments_array =
FACTORY->NewFixedArray(js_args.argc());
@@ -692,11 +743,13 @@ Persistent<Context> Shell::CreateEvaluationContext() {
i::Handle<i::JSArray> arguments_jsarray =
FACTORY->NewJSArrayWithElements(arguments_array);
context->Global()->Set(String::New("arguments"),
- Utils::ToLocal(arguments_jsarray));
+ Utils::ToLocal(arguments_jsarray));
+#endif // USING_V8_SHARED
return context;
}
+#ifndef USING_V8_SHARED
void Shell::OnExit() {
if (i::FLAG_dump_counters) {
printf("+----------------------------------------+-------------+\n");
@@ -716,12 +769,18 @@ void Shell::OnExit() {
if (counters_file_ != NULL)
delete counters_file_;
}
+#endif // USING_V8_SHARED
static char* ReadChars(const char* name, int* size_out) {
// Release the V8 lock while reading files.
v8::Unlocker unlocker(Isolate::GetCurrent());
+#ifndef USING_V8_SHARED
FILE* file = i::OS::FOpen(name, "rb");
+#else
+ // TODO(yangguo@chromium.org): reading from a directory hangs!
+ FILE* file = fopen(name, "rb");
+#endif // USING_V8_SHARED
if (file == NULL) return NULL;
fseek(file, 0, SEEK_END);
@@ -740,6 +799,7 @@ static char* ReadChars(const char* name, int* size_out) {
}
+#ifndef USING_V8_SHARED
static char* ReadToken(char* data, char token) {
char* next = i::OS::StrChr(data, token);
if (next != NULL) {
@@ -759,6 +819,7 @@ static char* ReadLine(char* data) {
static char* ReadWord(char* data) {
return ReadToken(data, ' ');
}
+#endif // USING_V8_SHARED
// Reads a file into a v8 string.
@@ -773,34 +834,44 @@ Handle<String> Shell::ReadFile(const char* name) {
void Shell::RunShell() {
+ Locker locker;
+ Context::Scope context_scope(evaluation_context_);
+ HandleScope handle_scope;
+ Handle<String> name = String::New("(d8)");
+#ifndef USING_V8_SHARED
LineEditor* editor = LineEditor::Get();
printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
if (i::FLAG_debugger) {
printf("JavaScript debugger enabled\n");
}
-
editor->Open();
while (true) {
- Locker locker;
- HandleScope handle_scope;
- Context::Scope context_scope(evaluation_context_);
i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
- if (input.is_empty())
- break;
+ if (input.is_empty()) break;
editor->AddHistory(*input);
- Handle<String> name = String::New("(d8)");
ExecuteString(String::New(*input), name, true, true);
}
editor->Close();
+#else
+ printf("V8 version %s [D8 light using shared library]\n", V8::GetVersion());
+ static const int kBufferSize = 256;
+ while (true) {
+ char buffer[kBufferSize];
+ printf("%s", Shell::kPrompt);
+ if (fgets(buffer, kBufferSize, stdin) == NULL) break;
+ ExecuteString(String::New(buffer), name, true, true);
+ }
+#endif // USING_V8_SHARED
printf("\n");
}
+#ifndef USING_V8_SHARED
class ShellThread : public i::Thread {
public:
ShellThread(int no, i::Vector<const char> files)
- : Thread("d8:ShellThread"),
- no_(no), files_(files) { }
+ : Thread("d8:ShellThread"),
+ no_(no), files_(files) { }
virtual void Run();
private:
int no_;
@@ -848,6 +919,7 @@ void ShellThread::Run() {
ptr = next_line;
}
}
+#endif // USING_V8_SHARED
void SourceGroup::ExitShell(int exit_code) {
@@ -894,7 +966,12 @@ void SourceGroup::Execute() {
Handle<String> SourceGroup::ReadFile(const char* name) {
+#ifndef USING_V8_SHARED
+ FILE* file = i::OS::FOpen(name, "rb");
+#else
+ // TODO(yangguo@chromium.org): reading from a directory hangs!
FILE* file = fopen(name, "rb");
+#endif // USING_V8_SHARED
if (file == NULL) return Handle<String>();
fseek(file, 0, SEEK_END);
@@ -914,6 +991,7 @@ Handle<String> SourceGroup::ReadFile(const char* name) {
}
+#ifndef USING_V8_SHARED
i::Thread::Options SourceGroup::GetThreadOptions() {
i::Thread::Options options;
options.name = "IsolateThread";
@@ -965,6 +1043,7 @@ void SourceGroup::WaitForThread() {
done_semaphore_->Wait();
}
}
+#endif // USING_V8_SHARED
bool Shell::SetOptions(int argc, char* argv[]) {
@@ -986,12 +1065,26 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.test_shell = true;
argv[i] = NULL;
} else if (strcmp(argv[i], "--preemption") == 0) {
+#ifdef USING_V8_SHARED
+ printf("D8 with shared library does not support multi-threading\n");
+ return false;
+#else
options.use_preemption = true;
argv[i] = NULL;
+#endif // USING_V8_SHARED
} else if (strcmp(argv[i], "--no-preemption") == 0) {
+#ifdef USING_V8_SHARED
+ printf("D8 with shared library does not support multi-threading\n");
+ return false;
+#else
options.use_preemption = false;
argv[i] = NULL;
+#endif // USING_V8_SHARED
} else if (strcmp(argv[i], "--preemption-interval") == 0) {
+#ifdef USING_V8_SHARED
+ printf("D8 with shared library does not support multi-threading\n");
+ return false;
+#else
if (++i < argc) {
argv[i-1] = NULL;
char* end = NULL;
@@ -1007,15 +1100,33 @@ bool Shell::SetOptions(int argc, char* argv[]) {
printf("Missing value for --preemption-interval\n");
return false;
}
+#endif // USING_V8_SHARED
} else if (strcmp(argv[i], "-f") == 0) {
// Ignore any -f flags for compatibility with other stand-alone
// JavaScript engines.
continue;
} else if (strcmp(argv[i], "--isolate") == 0) {
+#ifdef USING_V8_SHARED
+ printf("D8 with shared library does not support multi-threading\n");
+ return false;
+#endif // USING_V8_SHARED
options.num_isolates++;
}
+#ifdef USING_V8_SHARED
+ else if (strcmp(argv[i], "--dump-counters") == 0) {
+ printf("D8 with shared library does not include counters\n");
+ return false;
+ } else if (strcmp(argv[i], "-p") == 0) {
+ printf("D8 with shared library does not support multi-threading\n");
+ return false;
+ } else if (strcmp(argv[i], "--debugger") == 0) {
+ printf("Javascript debugger not included\n");
+ return false;
+ }
+#endif // USING_V8_SHARED
}
+#ifndef USING_V8_SHARED
// Run parallel threads if we are not using --isolate
for (int i = 1; i < argc; i++) {
if (argv[i] == NULL) continue;
@@ -1038,6 +1149,7 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.parallel_files->Add(i::Vector<const char>(files, size));
}
}
+#endif // USING_V8_SHARED
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
@@ -1062,21 +1174,21 @@ bool Shell::SetOptions(int argc, char* argv[]) {
int Shell::RunMain(int argc, char* argv[]) {
+#ifndef USING_V8_SHARED
i::List<i::Thread*> threads(1);
-
- {
- if (options.parallel_files != NULL)
- for (int i = 0; i < options.parallel_files->length(); i++) {
- i::Vector<const char> files = options.parallel_files->at(i);
- ShellThread* thread = new ShellThread(threads.length(), files);
- thread->Start();
- threads.Add(thread);
- }
-
- for (int i = 1; i < options.num_isolates; ++i) {
- options.isolate_sources[i].StartExecuteInThread();
+ if (options.parallel_files != NULL)
+ for (int i = 0; i < options.parallel_files->length(); i++) {
+ i::Vector<const char> files = options.parallel_files->at(i);
+ ShellThread* thread = new ShellThread(threads.length(), files);
+ thread->Start();
+ threads.Add(thread);
}
+ for (int i = 1; i < options.num_isolates; ++i) {
+ options.isolate_sources[i].StartExecuteInThread();
+ }
+#endif // USING_V8_SHARED
+ { // NOLINT
Locker lock;
HandleScope scope;
Persistent<Context> context = CreateEvaluationContext();
@@ -1090,14 +1202,18 @@ int Shell::RunMain(int argc, char* argv[]) {
} else {
context.Dispose();
}
+
+#ifndef USING_V8_SHARED
// Start preemption if threads have been created and preemption is enabled.
if (options.parallel_files != NULL
&& threads.length() > 0
&& options.use_preemption) {
Locker::StartPreemption(options.preemption_interval);
}
+#endif // USING_V8_SHARED
}
+#ifndef USING_V8_SHARED
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].WaitForThread();
}
@@ -1110,6 +1226,7 @@ int Shell::RunMain(int argc, char* argv[]) {
}
OnExit();
+#endif // USING_V8_SHARED
return 0;
}
@@ -1136,14 +1253,15 @@ int Shell::Main(int argc, char* argv[]) {
result = RunMain(argc, argv);
}
-#ifdef ENABLE_DEBUGGER_SUPPORT
+
+#if !defined(USING_V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
// Run remote debugger if requested, but never on --test
if (i::FLAG_remote_debugger && !options.test_shell) {
InstallUtilityScript();
RunRemoteDebugger(i::FLAG_debugger_port);
return 0;
}
-#endif
+#endif // !USING_V8_SHARED && ENABLE_DEBUGGER_SUPPORT
// Run interactive shell if explicitly requested or if no script has been
// executed, but never on --test
@@ -1151,7 +1269,9 @@ int Shell::Main(int argc, char* argv[]) {
if (( options.interactive_shell
|| !options.script_executed )
&& !options.test_shell ) {
+#ifndef USING_V8_SHARED
InstallUtilityScript();
+#endif // USING_V8_SHARED
RunShell();
}
diff --git a/deps/v8/src/d8.gyp b/deps/v8/src/d8.gyp
index 85914ec67..d2b425403 100644
--- a/deps/v8/src/d8.gyp
+++ b/deps/v8/src/d8.gyp
@@ -26,12 +26,14 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'variables': {
+ 'console%': '',
+ },
'targets': [
{
'target_name': 'd8',
'type': 'executable',
'dependencies': [
- 'd8_js2c#host',
'../tools/gyp/v8.gyp:v8',
],
'include_dirs+': [
@@ -42,15 +44,24 @@
],
'sources': [
'd8.cc',
- 'd8-debug.cc',
- '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc',
],
'conditions': [
- [ 'OS=="linux" or OS=="mac" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
- 'sources': [ 'd8-posix.cc', ]
- }],
- [ 'OS=="win"', {
- 'sources': [ 'd8-windows.cc', ]
+ [ 'component!="shared_library"', {
+ 'dependencies': [ 'd8_js2c#host', ],
+ 'sources': [ 'd8-debug.cc', '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc', ],
+ 'conditions': [
+ [ 'console=="readline"', {
+ 'libraries': [ '-lreadline', ],
+ 'sources': [ 'd8-readline.cc' ],
+ }],
+ [ '(OS=="linux" or OS=="mac" or OS=="freebsd" \
+ or OS=="openbsd" or OS=="solaris")', {
+ 'sources': [ 'd8-posix.cc', ]
+ }],
+ [ 'OS=="win"', {
+ 'sources': [ 'd8-windows.cc', ]
+ }],
+ ],
}],
],
},
diff --git a/deps/v8/src/d8.h b/deps/v8/src/d8.h
index 7f0272710..840ca1e8f 100644
--- a/deps/v8/src/d8.h
+++ b/deps/v8/src/d8.h
@@ -28,16 +28,23 @@
#ifndef V8_D8_H_
#define V8_D8_H_
-#include "allocation.h"
+
+#ifndef USING_V8_SHARED
#include "v8.h"
+#include "allocation.h"
#include "hashmap.h"
+#else
+#include "../include/v8.h"
+#endif // USING_V8_SHARED
namespace v8 {
-
+#ifndef USING_V8_SHARED
namespace i = v8::internal;
+#endif // USING_V8_SHARED
+#ifndef USING_V8_SHARED
// A single counter in a counter collection.
class Counter {
public:
@@ -110,17 +117,20 @@ class CounterMap {
static bool Match(void* key1, void* key2);
i::HashMap hash_map_;
};
+#endif // USING_V8_SHARED
class SourceGroup {
public:
- SourceGroup()
- : next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
- done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
- thread_(NULL),
- argv_(NULL),
- begin_offset_(0),
- end_offset_(0) { }
+ SourceGroup() :
+#ifndef USING_V8_SHARED
+ next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
+ done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
+ thread_(NULL),
+#endif // USING_V8_SHARED
+ argv_(NULL),
+ begin_offset_(0),
+ end_offset_(0) { }
void Begin(char** argv, int offset) {
argv_ = const_cast<const char**>(argv);
@@ -131,6 +141,7 @@ class SourceGroup {
void Execute();
+#ifndef USING_V8_SHARED
void StartExecuteInThread();
void WaitForThread();
@@ -154,6 +165,7 @@ class SourceGroup {
i::Semaphore* next_semaphore_;
i::Semaphore* done_semaphore_;
i::Thread* thread_;
+#endif // USING_V8_SHARED
void ExitShell(int exit_code);
Handle<String> ReadFile(const char* name);
@@ -166,34 +178,41 @@ class SourceGroup {
class ShellOptions {
public:
- ShellOptions()
- : script_executed(false),
- last_run(true),
- stress_opt(false),
- stress_deopt(false),
- interactive_shell(false),
- test_shell(false),
- use_preemption(true),
- preemption_interval(10),
- num_isolates(1),
- isolate_sources(NULL),
- parallel_files(NULL) { }
-
+ ShellOptions() :
+#ifndef USING_V8_SHARED
+ use_preemption(true),
+ preemption_interval(10),
+ parallel_files(NULL),
+#endif // USING_V8_SHARED
+ script_executed(false),
+ last_run(true),
+ stress_opt(false),
+ stress_deopt(false),
+ interactive_shell(false),
+ test_shell(false),
+ num_isolates(1),
+ isolate_sources(NULL) { }
+
+#ifndef USING_V8_SHARED
+ bool use_preemption;
+ int preemption_interval;
+ i::List< i::Vector<const char> >* parallel_files;
+#endif // USING_V8_SHARED
bool script_executed;
bool last_run;
bool stress_opt;
bool stress_deopt;
bool interactive_shell;
bool test_shell;
- bool use_preemption;
- int preemption_interval;
int num_isolates;
SourceGroup* isolate_sources;
- i::List< i::Vector<const char> >* parallel_files;
};
-
-class Shell: public i::AllStatic {
+#ifdef USING_V8_SHARED
+class Shell {
+#else
+class Shell : public i::AllStatic {
+#endif // USING_V8_SHARED
public:
static bool ExecuteString(Handle<String> source,
Handle<Value> name,
@@ -201,6 +220,14 @@ class Shell: public i::AllStatic {
bool report_exceptions);
static const char* ToCString(const v8::String::Utf8Value& value);
static void ReportException(TryCatch* try_catch);
+ static Handle<String> ReadFile(const char* name);
+ static Persistent<Context> CreateEvaluationContext();
+ static int RunMain(int argc, char* argv[]);
+ static int Main(int argc, char* argv[]);
+
+#ifndef USING_V8_SHARED
+ static Handle<Array> GetCompletions(Handle<String> text,
+ Handle<String> full);
static void OnExit();
static int* LookupCounter(const char* name);
static void* CreateHistogram(const char* name,
@@ -209,18 +236,8 @@ class Shell: public i::AllStatic {
size_t buckets);
static void AddHistogramSample(void* histogram, int sample);
static void MapCounters(const char* name);
- static Handle<String> ReadFile(const char* name);
- static void Initialize();
- static Persistent<Context> CreateEvaluationContext();
- static void InstallUtilityScript();
- static void RunShell();
- static bool SetOptions(int argc, char* argv[]);
- static int RunScript(char* filename);
- static int RunMain(int argc, char* argv[]);
- static int Main(int argc, char* argv[]);
- static Handle<ObjectTemplate> CreateGlobalTemplate();
- static Handle<Array> GetCompletions(Handle<String> text,
- Handle<String> full);
+#endif // USING_V8_SHARED
+
#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<Object> DebugMessageDetails(Handle<String> message);
static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
@@ -283,15 +300,16 @@ class Shell: public i::AllStatic {
static Handle<Value> RemoveDirectory(const Arguments& args);
static void AddOSMethods(Handle<ObjectTemplate> os_template);
-
+#ifndef USING_V8_SHARED
static const char* kHistoryFileName;
+#endif // USING_V8_SHARED
static const char* kPrompt;
-
static ShellOptions options;
private:
- static Persistent<Context> utility_context_;
static Persistent<Context> evaluation_context_;
+#ifndef USING_V8_SHARED
+ static Persistent<Context> utility_context_;
static CounterMap* counter_map_;
// We statically allocate a set of local counters to be used if we
// don't want to store the stats in a memory-mapped file
@@ -299,7 +317,14 @@ class Shell: public i::AllStatic {
static CounterCollection* counters_;
static i::OS::MemoryMappedFile* counters_file_;
static i::Mutex* context_mutex_;
+
static Counter* GetCounter(const char* name, bool is_histogram);
+ static void InstallUtilityScript();
+#endif // USING_V8_SHARED
+ static void Initialize();
+ static void RunShell();
+ static bool SetOptions(int argc, char* argv[]);
+ static Handle<ObjectTemplate> CreateGlobalTemplate();
static Handle<Value> CreateExternalArray(const Arguments& args,
ExternalArrayType type,
size_t element_size);
@@ -307,6 +332,7 @@ class Shell: public i::AllStatic {
};
+#ifndef USING_V8_SHARED
class LineEditor {
public:
enum Type { DUMB = 0, READLINE = 1 };
@@ -326,6 +352,7 @@ class LineEditor {
LineEditor* next_;
static LineEditor* first_;
};
+#endif // USING_V8_SHARED
} // namespace v8
diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc
index c48e514ab..aecbb463b 100644
--- a/deps/v8/src/debug.cc
+++ b/deps/v8/src/debug.cc
@@ -772,9 +772,9 @@ bool Debug::CompileDebuggerScript(int index) {
bool caught_exception = false;
Handle<JSFunction> function =
factory->NewFunctionFromSharedFunctionInfo(function_info, context);
- Handle<Object> result =
- Execution::TryCall(function, Handle<Object>(context->global()),
- 0, NULL, &caught_exception);
+
+ Execution::TryCall(function, Handle<Object>(context->global()),
+ 0, NULL, &caught_exception);
// Check for caught exceptions.
if (caught_exception) {
@@ -1886,8 +1886,7 @@ void Debug::ClearMirrorCache() {
*function_name));
ASSERT(fun->IsJSFunction());
bool caught_exception;
- Handle<Object> js_object = Execution::TryCall(
- Handle<JSFunction>::cast(fun),
+ Execution::TryCall(Handle<JSFunction>::cast(fun),
Handle<JSObject>(Debug::debug_context()->global()),
0, NULL, &caught_exception);
}
@@ -2252,8 +2251,7 @@ void Debugger::OnAfterCompile(Handle<Script> script,
bool caught_exception = false;
const int argc = 1;
Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
- Handle<Object> result = Execution::TryCall(
- Handle<JSFunction>::cast(update_script_break_points),
+ Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
Isolate::Current()->js_builtins_object(), argc, argv,
&caught_exception);
if (caught_exception) {
@@ -2930,7 +2928,7 @@ v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
// Isolate::context() may be NULL when "script collected" event occures.
ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
- return GetDebugEventContext(isolate);
+ return context;
}
diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc
index 175ee6e1f..3a7b33a21 100644
--- a/deps/v8/src/deoptimizer.cc
+++ b/deps/v8/src/deoptimizer.cc
@@ -1462,7 +1462,7 @@ DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
}
void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
- v->VisitPointer(reinterpret_cast<Object**>(&function_));
+ v->VisitPointer(BitCast<Object**>(&function_));
v->VisitPointers(parameters_, parameters_ + parameters_count_);
v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
}
diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc
index 9ba48ee50..ac96668d9 100644
--- a/deps/v8/src/factory.cc
+++ b/deps/v8/src/factory.cc
@@ -892,6 +892,13 @@ Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
}
+void Factory::BecomeJSObject(Handle<JSProxy> object) {
+ CALL_HEAP_FUNCTION_VOID(
+ isolate(),
+ isolate()->heap()->ReinitializeJSProxyAsJSObject(*object));
+}
+
+
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name,
int number_of_literals,
diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h
index 19f09a15c..19f382793 100644
--- a/deps/v8/src/factory.h
+++ b/deps/v8/src/factory.h
@@ -253,6 +253,9 @@ class Factory {
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
+ // Change the type of the argument into a regular JS object and reinitialize.
+ void BecomeJSObject(Handle<JSProxy> object);
+
Handle<JSFunction> NewFunction(Handle<String> name,
Handle<Object> prototype);
diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc
index eaf09ebaf..bebd10a80 100644
--- a/deps/v8/src/frames.cc
+++ b/deps/v8/src/frames.cc
@@ -371,7 +371,6 @@ Code* StackFrame::GetSafepointData(Isolate* isolate,
unsigned* stack_slots) {
PcToCodeCache::PcToCodeCacheEntry* entry =
isolate->pc_to_code_cache()->GetCacheEntry(pc);
- SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
if (!entry->safepoint_entry.is_valid()) {
entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
ASSERT(entry->safepoint_entry.is_valid());
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc
index 0b91f5446..8c2f0d178 100644
--- a/deps/v8/src/full-codegen.cc
+++ b/deps/v8/src/full-codegen.cc
@@ -686,7 +686,6 @@ FullCodeGenerator::InlineFunctionGenerator
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments();
- Handle<String> name = node->name();
const Runtime::Function* function = node->function();
ASSERT(function != NULL);
ASSERT(function->intrinsic_type == Runtime::INLINE);
diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h
index 5ab9806ed..bb9d0a8e8 100644
--- a/deps/v8/src/globals.h
+++ b/deps/v8/src/globals.h
@@ -1,4 +1,4 @@
-// Copyright 2010 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:
@@ -199,6 +199,8 @@ const int kDoubleSize = sizeof(double); // NOLINT
const int kIntptrSize = sizeof(intptr_t); // NOLINT
const int kPointerSize = sizeof(void*); // NOLINT
+const int kDoubleSizeLog2 = 3;
+
#if V8_HOST_ARCH_64_BIT
const int kPointerSizeLog2 = 3;
const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index 98a2d3374..8dbda270f 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -3267,14 +3267,13 @@ MaybeObject* Heap::AllocateJSProxy(Object* handler, Object* prototype) {
MaybeObject* maybe_map_obj = AllocateMap(JS_PROXY_TYPE, JSProxy::kSize);
if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
map->set_prototype(prototype);
- map->set_pre_allocated_property_fields(1);
- map->set_inobject_properties(1);
// Allocate the proxy object.
Object* result;
MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
if (!maybe_result->ToObject(&result)) return maybe_result;
JSProxy::cast(result)->set_handler(handler);
+ JSProxy::cast(result)->set_padding(Smi::FromInt(0));
return result;
}
@@ -3414,6 +3413,36 @@ MaybeObject* Heap::CopyJSObject(JSObject* source) {
}
+MaybeObject* Heap::ReinitializeJSProxyAsJSObject(JSProxy* object) {
+ // Allocate fresh map.
+ // TODO(rossberg): Once we optimize proxies, cache these maps.
+ Map* map;
+ MaybeObject* maybe_map_obj =
+ AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+ if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
+
+ // Check that the receiver has the same size as a fresh object.
+ ASSERT(map->instance_size() == object->map()->instance_size());
+
+ map->set_prototype(object->map()->prototype());
+
+ // Allocate the backing storage for the properties.
+ int prop_size = map->unused_property_fields() - map->inobject_properties();
+ Object* properties;
+ { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED);
+ if (!maybe_properties->ToObject(&properties)) return maybe_properties;
+ }
+
+ // Reset the map for the object.
+ object->set_map(map);
+
+ // Reinitialize the object from the constructor map.
+ InitializeJSObjectFromMap(JSObject::cast(object),
+ FixedArray::cast(properties), map);
+ return object;
+}
+
+
MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
JSGlobalProxy* object) {
ASSERT(constructor->has_initial_map());
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h
index d90a681d4..6cd4f840b 100644
--- a/deps/v8/src/heap.h
+++ b/deps/v8/src/heap.h
@@ -441,6 +441,11 @@ class Heap {
MUST_USE_RESULT MaybeObject* AllocateJSProxy(Object* handler,
Object* prototype);
+ // Reinitialize a JSProxy into an (empty) JSObject. The receiver
+ // must have the same size as an empty object. The object is reinitialized
+ // and behaves as an object that has been freshly allocated.
+ MUST_USE_RESULT MaybeObject* ReinitializeJSProxyAsJSObject(JSProxy* object);
+
// Reinitialize an JSGlobalProxy based on a constructor. The object
// must have the same size as objects allocated using the
// constructor. The object is reinitialized and behaves as an
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc
index 50f2f6df6..d282f3781 100644
--- a/deps/v8/src/hydrogen-instructions.cc
+++ b/deps/v8/src/hydrogen-instructions.cc
@@ -1366,6 +1366,19 @@ bool HLoadKeyedFastElement::RequiresHoleCheck() const {
}
+void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+ elements()->PrintNameTo(stream);
+ stream->Add("[");
+ key()->PrintNameTo(stream);
+ stream->Add("]");
+}
+
+
+bool HLoadKeyedFastDoubleElement::RequiresHoleCheck() const {
+ return true;
+}
+
+
void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");
@@ -1451,6 +1464,15 @@ void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
+void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+ elements()->PrintNameTo(stream);
+ stream->Add("[");
+ key()->PrintNameTo(stream);
+ stream->Add("] = ");
+ value()->PrintNameTo(stream);
+}
+
+
void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");
diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h
index 401c2e4a0..15186ff26 100644
--- a/deps/v8/src/hydrogen-instructions.h
+++ b/deps/v8/src/hydrogen-instructions.h
@@ -131,6 +131,7 @@ class LChunkBuilder;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
+ V(LoadKeyedFastDoubleElement) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
@@ -156,6 +157,7 @@ class LChunkBuilder;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
+ V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@@ -588,9 +590,9 @@ class HValue: public ZoneObject {
// it would otherwise output what should be a minus zero as an int32 zero.
// If the operation also exists in a form that takes int32 and outputs int32
// then the operation should return its input value so that we can propagate
- // back. There are two operations that need to propagate back to more than
- // one input. They are phi and binary add. They always return NULL and
- // expect the caller to take care of things.
+ // back. There are three operations that need to propagate back to more than
+ // one input. They are phi and binary div and mul. They always return NULL
+ // and expect the caller to take care of things.
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
visited->Add(id());
return NULL;
@@ -1123,40 +1125,19 @@ class HChange: public HUnaryOperation {
class HClampToUint8: public HUnaryOperation {
public:
explicit HClampToUint8(HValue* value)
- : HUnaryOperation(value),
- input_rep_(Representation::None()) {
- SetFlag(kFlexibleRepresentation);
- set_representation(Representation::Tagged());
+ : HUnaryOperation(value) {
+ set_representation(Representation::Integer32());
SetFlag(kUseGVN);
}
virtual Representation RequiredInputRepresentation(int index) const {
- return input_rep_;
- }
-
- virtual Representation InferredRepresentation() {
- // TODO(danno): Inference on input types should happen separately from
- // return representation.
- Representation new_rep = value()->representation();
- if (input_rep_.IsNone()) {
- if (!new_rep.IsNone()) {
- input_rep_ = new_rep;
- return Representation::Integer32();
- } else {
- return Representation::None();
- }
- } else {
- return Representation::Integer32();
- }
+ return Representation::None();
}
DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
protected:
virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- Representation input_rep_;
};
@@ -3540,6 +3521,37 @@ class HLoadKeyedFastElement: public HTemplateInstruction<2> {
};
+class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
+ public:
+ HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
+ SetOperandAt(0, elements);
+ SetOperandAt(1, key);
+ set_representation(Representation::Double());
+ SetFlag(kDependsOnArrayElements);
+ SetFlag(kUseGVN);
+ }
+
+ HValue* elements() { return OperandAt(0); }
+ HValue* key() { return OperandAt(1); }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ // The key is supposed to be Integer32.
+ return index == 0
+ ? Representation::Tagged()
+ : Representation::Integer32();
+ }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ bool RequiresHoleCheck() const;
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
+
+ protected:
+ virtual bool DataEquals(HValue* other) { return true; }
+};
+
+
class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
public:
HLoadKeyedSpecializedArrayElement(HValue* external_elements,
@@ -3725,6 +3737,41 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> {
};
+class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
+ public:
+ HStoreKeyedFastDoubleElement(HValue* elements,
+ HValue* key,
+ HValue* val) {
+ SetOperandAt(0, elements);
+ SetOperandAt(1, key);
+ SetOperandAt(2, val);
+ SetFlag(kChangesArrayElements);
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ if (index == 1) {
+ return Representation::Integer32();
+ } else if (index == 2) {
+ return Representation::Double();
+ } else {
+ return Representation::Tagged();
+ }
+ }
+
+ HValue* elements() { return OperandAt(0); }
+ HValue* key() { return OperandAt(1); }
+ HValue* value() { return OperandAt(2); }
+
+ bool NeedsWriteBarrier() {
+ return StoringValueNeedsWriteBarrier(value());
+ }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
+};
+
+
class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
public:
HStoreKeyedSpecializedArrayElement(HValue* external_elements,
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index 887ba7360..7e62ec4c4 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -1666,8 +1666,8 @@ void HInferRepresentation::Analyze() {
HValue* use = it.value();
if (use->IsPhi()) {
int id = HPhi::cast(use)->phi_id();
- change = change ||
- connected_phis[i]->UnionIsChanged(*connected_phis[id]);
+ if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
+ change = true;
}
}
}
@@ -3901,7 +3901,9 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
bool is_store) {
ASSERT(expr->IsMonomorphic());
Handle<Map> map = expr->GetMonomorphicReceiverType();
- if (!map->has_fast_elements() && !map->has_external_array_elements()) {
+ if (!map->has_fast_elements() &&
+ !map->has_fast_double_elements() &&
+ !map->has_external_array_elements()) {
return is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key);
}
@@ -3920,20 +3922,39 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
return BuildExternalArrayElementAccess(external_elements, checked_key,
val, map->elements_kind(), is_store);
}
- ASSERT(map->has_fast_elements());
+ bool fast_double_elements = map->has_fast_double_elements();
+ ASSERT(map->has_fast_elements() || fast_double_elements);
if (map->instance_type() == JS_ARRAY_TYPE) {
length = AddInstruction(new(zone()) HJSArrayLength(object));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
AddInstruction(elements);
+ if (is_store && !fast_double_elements) {
+ AddInstruction(new(zone()) HCheckMap(
+ elements, isolate()->factory()->fixed_array_map()));
+ }
} else {
AddInstruction(elements);
+ if (is_store && !fast_double_elements) {
+ AddInstruction(new(zone()) HCheckMap(
+ elements, isolate()->factory()->fixed_array_map()));
+ }
length = AddInstruction(new(zone()) HFixedArrayLength(elements));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
}
if (is_store) {
- return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
+ if (fast_double_elements) {
+ return new(zone()) HStoreKeyedFastDoubleElement(elements,
+ checked_key,
+ val);
+ } else {
+ return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
+ }
} else {
- return new(zone()) HLoadKeyedFastElement(elements, checked_key);
+ if (fast_double_elements) {
+ return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
+ } else {
+ return new(zone()) HLoadKeyedFastElement(elements, checked_key);
+ }
}
}
@@ -3966,8 +3987,6 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
todo_external_array = true;
}
}
- // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt.
- type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false;
HBasicBlock* join = graph()->CreateBasicBlock();
@@ -4016,7 +4035,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_true);
HInstruction* access;
- if (elements_kind == JSObject::FAST_ELEMENTS) {
+ if (elements_kind == JSObject::FAST_ELEMENTS ||
+ elements_kind == JSObject::FAST_DOUBLE_ELEMENTS) {
HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
HHasInstanceTypeAndBranch* typecheck =
@@ -4032,12 +4052,28 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
elements = AddInstruction(new(zone()) HLoadElements(object));
elements->ClearFlag(HValue::kUseGVN);
+ bool fast_double_elements =
+ elements_kind == JSObject::FAST_DOUBLE_ELEMENTS;
if (is_store) {
- access = AddInstruction(
- new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastDoubleElement(elements,
+ checked_key,
+ val));
+ } else {
+ AddInstruction(new(zone()) HCheckMap(
+ elements, isolate()->factory()->fixed_array_map()));
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
+ }
} else {
- access = AddInstruction(
- new(zone()) HLoadKeyedFastElement(elements, checked_key));
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
+ } else {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastElement(elements, checked_key));
+ }
Push(access);
}
*has_side_effects |= access->HasSideEffects();
@@ -4049,14 +4085,30 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_fastobject);
elements = AddInstruction(new(zone()) HLoadElements(object));
elements->ClearFlag(HValue::kUseGVN);
+ if (is_store && !fast_double_elements) {
+ AddInstruction(new(zone()) HCheckMap(
+ elements, isolate()->factory()->fixed_array_map()));
+ }
length = AddInstruction(new(zone()) HFixedArrayLength(elements));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
if (is_store) {
- access = AddInstruction(
- new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastDoubleElement(elements,
+ checked_key,
+ val));
+ } else {
+ access = AddInstruction(
+ new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
+ }
} else {
- access = AddInstruction(
- new(zone()) HLoadKeyedFastElement(elements, checked_key));
+ if (fast_double_elements) {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
+ } else {
+ access = AddInstruction(
+ new(zone()) HLoadKeyedFastElement(elements, checked_key));
+ }
}
} else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) {
if (is_store) {
diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc
index 48bd8b1a5..71aacf9a3 100644
--- a/deps/v8/src/ia32/code-stubs-ia32.cc
+++ b/deps/v8/src/ia32/code-stubs-ia32.cc
@@ -4158,6 +4158,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor =
masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
+ __ SetCallKind(ecx, CALL_AS_METHOD);
__ jmp(adaptor, RelocInfo::CODE_TARGET);
}
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc
index 6293718f6..7211ba49a 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc
@@ -2230,10 +2230,34 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
}
-Operand LCodeGen::BuildExternalArrayOperand(
+void LCodeGen::DoLoadKeyedFastDoubleElement(
+ LLoadKeyedFastDoubleElement* instr) {
+ Register elements = ToRegister(instr->elements());
+ XMMRegister result = ToDoubleRegister(instr->result());
+
+ if (instr->hydrogen()->RequiresHoleCheck()) {
+ int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
+ sizeof(kHoleNanLower32);
+ Operand hole_check_operand = BuildFastArrayOperand(
+ instr->elements(), instr->key(),
+ JSObject::FAST_DOUBLE_ELEMENTS,
+ offset);
+ __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
+ DeoptimizeIf(equal, instr->environment());
+ }
+
+ Operand double_load_operand = BuildFastArrayOperand(
+ instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+ __ movdbl(result, double_load_operand);
+}
+
+
+Operand LCodeGen::BuildFastArrayOperand(
LOperand* external_pointer,
LOperand* key,
- JSObject::ElementsKind elements_kind) {
+ JSObject::ElementsKind elements_kind,
+ uint32_t offset) {
Register external_pointer_reg = ToRegister(external_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
if (key->IsConstantOperand()) {
@@ -2241,10 +2265,11 @@ Operand LCodeGen::BuildExternalArrayOperand(
if (constant_value & 0xF0000000) {
Abort("array index constant value too big");
}
- return Operand(external_pointer_reg, constant_value * (1 << shift_size));
+ return Operand(external_pointer_reg,
+ constant_value * (1 << shift_size) + offset);
} else {
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
- return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
+ return Operand(external_pointer_reg, ToRegister(key), scale_factor, offset);
}
}
@@ -2252,8 +2277,8 @@ Operand LCodeGen::BuildExternalArrayOperand(
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
- Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
- instr->key(), elements_kind));
+ Operand operand(BuildFastArrayOperand(instr->external_pointer(),
+ instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
@@ -2790,7 +2815,8 @@ void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
__ ucomisd(input_reg, xmm0);
__ j(above, &positive, Label::kNear);
__ j(equal, &zero, Label::kNear);
- ExternalReference nan = ExternalReference::address_of_nan();
+ ExternalReference nan =
+ ExternalReference::address_of_canonical_non_hole_nan();
__ movdbl(input_reg, Operand::StaticVariable(nan));
__ jmp(&done, Label::kNear);
__ bind(&zero);
@@ -3000,8 +3026,8 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
- Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
- instr->key(), elements_kind));
+ Operand operand(BuildFastArrayOperand(instr->external_pointer(),
+ instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
__ movss(operand, xmm0);
@@ -3068,6 +3094,28 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
}
+void LCodeGen::DoStoreKeyedFastDoubleElement(
+ LStoreKeyedFastDoubleElement* instr) {
+ XMMRegister value = ToDoubleRegister(instr->value());
+ Register elements = ToRegister(instr->elements());
+ Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
+ Label have_value;
+
+ __ ucomisd(value, value);
+ __ j(parity_odd, &have_value); // NaN.
+
+ ExternalReference canonical_nan_reference =
+ ExternalReference::address_of_canonical_non_hole_nan();
+ __ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
+ __ bind(&have_value);
+
+ Operand double_store_operand = BuildFastArrayOperand(
+ instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+ __ movdbl(double_store_operand, value);
+}
+
+
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
@@ -3451,7 +3499,8 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
DeoptimizeIf(not_equal, env);
// Convert undefined to NaN.
- ExternalReference nan = ExternalReference::address_of_nan();
+ ExternalReference nan =
+ ExternalReference::address_of_canonical_non_hole_nan();
__ movdbl(result_reg, Operand::StaticVariable(nan));
__ jmp(&done, Label::kNear);
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.h b/deps/v8/src/ia32/lithium-codegen-ia32.h
index 7ab446dbf..c568bef5b 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.h
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.h
@@ -222,9 +222,10 @@ class LCodeGen BASE_EMBEDDED {
Register ToRegister(int index) const;
XMMRegister ToDoubleRegister(int index) const;
int ToInteger32(LConstantOperand* op) const;
- Operand BuildExternalArrayOperand(LOperand* external_pointer,
- LOperand* key,
- JSObject::ElementsKind elements_kind);
+ Operand BuildFastArrayOperand(LOperand* external_pointer,
+ LOperand* key,
+ JSObject::ElementsKind elements_kind,
+ uint32_t offset);
// Specific math operations - used from DoUnaryMathOperation.
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc
index 1b9aeb58c..9951d2540 100644
--- a/deps/v8/src/ia32/lithium-ia32.cc
+++ b/deps/v8/src/ia32/lithium-ia32.cc
@@ -429,6 +429,15 @@ void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
+void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+ elements()->PrintTo(stream);
+ stream->Add("[");
+ key()->PrintTo(stream);
+ stream->Add("] <- ");
+ value()->PrintTo(stream);
+}
+
+
void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add("[");
@@ -1878,6 +1887,18 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
}
+LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
+ HLoadKeyedFastDoubleElement* instr) {
+ ASSERT(instr->representation().IsDouble());
+ ASSERT(instr->key()->representation().IsInteger32());
+ LOperand* elements = UseRegisterAtStart(instr->elements());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+ LLoadKeyedFastDoubleElement* result =
+ new LLoadKeyedFastDoubleElement(elements, key);
+ return AssignEnvironment(DefineAsRegister(result));
+}
+
+
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
@@ -1933,6 +1954,20 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
}
+LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
+ HStoreKeyedFastDoubleElement* instr) {
+ ASSERT(instr->value()->representation().IsDouble());
+ ASSERT(instr->elements()->representation().IsTagged());
+ ASSERT(instr->key()->representation().IsInteger32());
+
+ LOperand* elements = UseRegisterAtStart(instr->elements());
+ LOperand* val = UseTempRegister(instr->value());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+
+ return new LStoreKeyedFastDoubleElement(elements, key, val);
+}
+
+
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());
diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h
index 0daab5f9d..6b60a6e40 100644
--- a/deps/v8/src/ia32/lithium-ia32.h
+++ b/deps/v8/src/ia32/lithium-ia32.h
@@ -116,6 +116,7 @@ class LCodeGen;
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastElement) \
+ V(LoadKeyedFastDoubleElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
V(LoadNamedField) \
@@ -141,6 +142,7 @@ class LCodeGen;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
+ V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@@ -1161,6 +1163,23 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
+class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadKeyedFastDoubleElement(LOperand* elements,
+ LOperand* key) {
+ inputs_[0] = elements;
+ inputs_[1] = key;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
+ "load-keyed-fast-double-element")
+ DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
+
+ LOperand* elements() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+};
+
+
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
@@ -1651,6 +1670,28 @@ class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
};
+class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+ LStoreKeyedFastDoubleElement(LOperand* elements,
+ LOperand* key,
+ LOperand* val) {
+ inputs_[0] = elements;
+ inputs_[1] = key;
+ inputs_[2] = val;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
+ "store-keyed-fast-double-element")
+ DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ LOperand* elements() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+ LOperand* value() { return inputs_[2]; }
+};
+
+
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index 136b24c98..3e037d79a 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -2044,6 +2044,9 @@ void MacroAssembler::AssertFastElements(Register elements) {
Immediate(factory->fixed_array_map()));
j(equal, &ok);
cmp(FieldOperand(elements, HeapObject::kMapOffset),
+ Immediate(factory->fixed_double_array_map()));
+ j(equal, &ok);
+ cmp(FieldOperand(elements, HeapObject::kMapOffset),
Immediate(factory->fixed_cow_array_map()));
j(equal, &ok);
Abort("JSObject with fast elements map has slow elements");
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index 266085088..9a690d76b 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -3790,6 +3790,71 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+ MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- eax : key
+ // -- edx : receiver
+ // -- esp[0] : return address
+ // -----------------------------------
+ Label miss_force_generic, slow_allocate_heapnumber;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(eax, &miss_force_generic);
+
+ // Get the elements array.
+ __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
+ __ AssertFastElements(ecx);
+
+ // Check that the key is within bounds.
+ __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset));
+ __ j(above_equal, &miss_force_generic);
+
+ // Check for the hole
+ uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+ __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32));
+ __ j(equal, &miss_force_generic);
+
+ // Always allocate a heap number for the result.
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(xmm0, FieldOperand(ecx, eax, times_4,
+ FixedDoubleArray::kHeaderSize));
+ } else {
+ __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize));
+ }
+ __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber);
+ // Set the value.
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
+ } else {
+ __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset));
+ }
+ __ mov(eax, ecx);
+ __ ret(0);
+
+ __ bind(&slow_allocate_heapnumber);
+ // A value was pushed on the floating point stack before the allocation, if
+ // the allocation fails it needs to be removed.
+ if (!CpuFeatures::IsSupported(SSE2)) {
+ __ ffree();
+ __ fincstp();
+ }
+ Handle<Code> slow_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_Slow();
+ __ jmp(slow_ic, RelocInfo::CODE_TARGET);
+
+ __ bind(&miss_force_generic);
+ Handle<Code> miss_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+ __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@@ -3839,6 +3904,98 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+ MacroAssembler* masm,
+ bool is_js_array) {
+ // ----------- S t a t e -------------
+ // -- eax : value
+ // -- ecx : key
+ // -- edx : receiver
+ // -- esp[0] : return address
+ // -----------------------------------
+ Label miss_force_generic, smi_value, is_nan, maybe_nan;
+ Label have_double_value, not_nan;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(ecx, &miss_force_generic);
+
+ // Get the elements array.
+ __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+ __ AssertFastElements(edi);
+
+ if (is_js_array) {
+ // Check that the key is within bounds.
+ __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
+ } else {
+ // Check that the key is within bounds.
+ __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
+ }
+ __ j(above_equal, &miss_force_generic);
+
+ __ JumpIfSmi(eax, &smi_value, Label::kNear);
+
+ __ CheckMap(eax,
+ masm->isolate()->factory()->heap_number_map(),
+ &miss_force_generic,
+ DONT_DO_SMI_CHECK);
+
+ // Double value, canonicalize NaN.
+ uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
+ __ cmp(FieldOperand(eax, offset), Immediate(kNaNOrInfinityLowerBoundUpper32));
+ __ j(greater_equal, &maybe_nan, Label::kNear);
+
+ __ bind(&not_nan);
+ ExternalReference canonical_nan_reference =
+ ExternalReference::address_of_canonical_non_hole_nan();
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ bind(&have_double_value);
+ __ movdbl(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize),
+ xmm0);
+ __ ret(0);
+ } else {
+ __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ bind(&have_double_value);
+ __ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
+ __ ret(0);
+ }
+
+ __ bind(&maybe_nan);
+ // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+ // it's an Infinity, and the non-NaN code path applies.
+ __ j(greater, &is_nan, Label::kNear);
+ __ cmp(FieldOperand(eax, HeapNumber::kValueOffset), Immediate(0));
+ __ j(zero, &not_nan);
+ __ bind(&is_nan);
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(xmm0, Operand::StaticVariable(canonical_nan_reference));
+ } else {
+ __ fld_d(Operand::StaticVariable(canonical_nan_reference));
+ }
+ __ jmp(&have_double_value, Label::kNear);
+
+ __ bind(&smi_value);
+ // Value is a smi. convert to a double and store.
+ __ SmiUntag(eax);
+ __ push(eax);
+ __ fild_s(Operand(esp, 0));
+ __ pop(eax);
+ __ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
+ __ ret(0);
+
+ // Handle store cache miss, replacing the ic with the generic stub.
+ __ bind(&miss_force_generic);
+ Handle<Code> ic_force_generic =
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+ __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+}
+
+
#undef __
} } // namespace v8::internal
diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc
index 45a39ffbc..bc47df8f2 100644
--- a/deps/v8/src/jsregexp.cc
+++ b/deps/v8/src/jsregexp.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -1958,13 +1958,10 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
ASSERT(characters_filled_in < details->characters());
int characters = details->characters();
int char_mask;
- int char_shift;
if (compiler->ascii()) {
char_mask = String::kMaxAsciiCharCode;
- char_shift = 8;
} else {
char_mask = String::kMaxUC16CharCode;
- char_shift = 16;
}
for (int k = 0; k < elms_->length(); k++) {
TextElement elm = elms_->at(k);
@@ -4888,7 +4885,6 @@ void TextNode::CalculateOffsets() {
cp_offset += elm.data.u_atom->data().length();
} else {
cp_offset++;
- Vector<const uc16> quarks = elm.data.u_atom->data();
}
}
}
@@ -5327,8 +5323,6 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
return CompilationResult(error_message);
}
- NodeInfo info = *node->info();
-
// Create the correct assembler for the architecture.
#ifndef V8_INTERPRETED_REGEXP
// Native regexp implementation.
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index b9281070a..aaa98ed4a 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -195,7 +195,8 @@ function FormatMessage(message) {
non_extensible_proto: ["%0", " is not extensible"],
handler_non_object: ["Proxy.", "%0", " called with non-object as handler"],
handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
- handler_failed: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
+ handler_returned_false: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
+ handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"],
proxy_prop_not_configurable: ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"],
proxy_non_object_prop_names: ["Trap ", "%1", " returned non-object ", "%0"],
proxy_repeated_prop_name: ["Trap ", "%1", " returned repeated property name ", "%2"],
@@ -1050,13 +1051,15 @@ function captureStackTrace(obj, cons_opt) {
$Math.__proto__ = global.Object.prototype;
-DefineError(function Error() { });
-DefineError(function TypeError() { });
-DefineError(function RangeError() { });
-DefineError(function SyntaxError() { });
-DefineError(function ReferenceError() { });
-DefineError(function EvalError() { });
-DefineError(function URIError() { });
+// DefineError is a native function. Use explicit receiver. Otherwise
+// the receiver will be 'undefined'.
+this.DefineError(function Error() { });
+this.DefineError(function TypeError() { });
+this.DefineError(function RangeError() { });
+this.DefineError(function SyntaxError() { });
+this.DefineError(function ReferenceError() { });
+this.DefineError(function EvalError() { });
+this.DefineError(function URIError() { });
$Error.captureStackTrace = captureStackTrace;
diff --git a/deps/v8/src/mips/assembler-mips.cc b/deps/v8/src/mips/assembler-mips.cc
index 4ca6a91aa..51642e05c 100644
--- a/deps/v8/src/mips/assembler-mips.cc
+++ b/deps/v8/src/mips/assembler-mips.cc
@@ -285,7 +285,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
unbound_labels_count_ = 0;
block_buffer_growth_ = false;
- ast_id_for_reloc_info_ = kNoASTId;
+ ClearRecordedAstId();
}
@@ -1947,9 +1947,8 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
}
ASSERT(buffer_space() >= kMaxRelocSize); // Too late to grow buffer here.
if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
- ASSERT(ast_id_for_reloc_info_ != kNoASTId);
- RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_);
- ast_id_for_reloc_info_ = kNoASTId;
+ RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId());
+ ClearRecordedAstId();
reloc_info_writer.Write(&reloc_info_with_ast_id);
} else {
reloc_info_writer.Write(&rinfo);
diff --git a/deps/v8/src/mips/assembler-mips.h b/deps/v8/src/mips/assembler-mips.h
index f3730d6f3..a16cd80ea 100644
--- a/deps/v8/src/mips/assembler-mips.h
+++ b/deps/v8/src/mips/assembler-mips.h
@@ -833,7 +833,17 @@ class Assembler : public AssemblerBase {
// Record the AST id of the CallIC being compiled, so that it can be placed
// in the relocation information.
- void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; }
+ void SetRecordedAstId(unsigned ast_id) {
+ ASSERT(recorded_ast_id_ == kNoASTId);
+ recorded_ast_id_ = ast_id;
+ }
+
+ unsigned RecordedAstId() {
+ ASSERT(recorded_ast_id_ != kNoASTId);
+ return recorded_ast_id_;
+ }
+
+ void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
// Record a comment relocation entry that can be used by a disassembler.
// Use --code-comments to enable.
@@ -926,7 +936,7 @@ class Assembler : public AssemblerBase {
// Relocation for a type-recording IC has the AST id added to it. This
// member variable is a way to pass the information from the call site to
// the relocation info.
- unsigned ast_id_for_reloc_info_;
+ unsigned recorded_ast_id_;
bool emit_debug_code() const { return emit_debug_code_; }
diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc
index d03443f27..d89d3e57c 100644
--- a/deps/v8/src/mips/code-stubs-mips.cc
+++ b/deps/v8/src/mips/code-stubs-mips.cc
@@ -4913,6 +4913,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ li(a0, Operand(argc_)); // Setup the number of arguments.
__ mov(a2, zero_reg);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
+ __ SetCallKind(t1, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
}
diff --git a/deps/v8/src/mips/macro-assembler-mips.cc b/deps/v8/src/mips/macro-assembler-mips.cc
index 712ceec95..5e8d676ac 100644
--- a/deps/v8/src/mips/macro-assembler-mips.cc
+++ b/deps/v8/src/mips/macro-assembler-mips.cc
@@ -2080,8 +2080,7 @@ void MacroAssembler::Call(Handle<Code> code,
bind(&start);
ASSERT(RelocInfo::IsCodeTarget(rmode));
if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) {
- ASSERT(ast_id_for_reloc_info_ == kNoASTId);
- ast_id_for_reloc_info_ = ast_id;
+ SetRecordedAstId(ast_id);
rmode = RelocInfo::CODE_TARGET_WITH_ID;
}
Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
@@ -3701,6 +3700,8 @@ void MacroAssembler::AssertFastElements(Register elements) {
lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
LoadRoot(at, Heap::kFixedArrayMapRootIndex);
Branch(&ok, eq, elements, Operand(at));
+ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
+ Branch(&ok, eq, elements, Operand(at));
LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
Branch(&ok, eq, elements, Operand(at));
Abort("JSObject with fast elements map has slow elements");
diff --git a/deps/v8/src/mips/stub-cache-mips.cc b/deps/v8/src/mips/stub-cache-mips.cc
index 919bdc40c..f1ffe9b63 100644
--- a/deps/v8/src/mips/stub-cache-mips.cc
+++ b/deps/v8/src/mips/stub-cache-mips.cc
@@ -4229,6 +4229,75 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+ MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- ra : return address
+ // -- a0 : key
+ // -- a1 : receiver
+ // -----------------------------------
+ Label miss_force_generic, slow_allocate_heapnumber;
+
+ Register key_reg = a0;
+ Register receiver_reg = a1;
+ Register elements_reg = a2;
+ Register heap_number_reg = a2;
+ Register indexed_double_offset = a3;
+ Register scratch = t0;
+ Register scratch2 = t1;
+ Register scratch3 = t2;
+ Register heap_number_map = t3;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+ // Get the elements array.
+ __ lw(elements_reg,
+ FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+ // Check that the key is within bounds.
+ __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+ __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
+
+ // Load the upper word of the double in the fixed array and test for NaN.
+ __ sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
+ __ Addu(indexed_double_offset, elements_reg, Operand(scratch2));
+ uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
+ __ lw(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
+ __ Branch(&miss_force_generic, eq, scratch, Operand(kHoleNanUpper32));
+
+ // Non-NaN. Allocate a new heap number and copy the double value into it.
+ __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
+ heap_number_map, &slow_allocate_heapnumber);
+
+ // Don't need to reload the upper 32 bits of the double, it's already in
+ // scratch.
+ __ sw(scratch, FieldMemOperand(heap_number_reg,
+ HeapNumber::kExponentOffset));
+ __ lw(scratch, FieldMemOperand(indexed_double_offset,
+ FixedArray::kHeaderSize));
+ __ sw(scratch, FieldMemOperand(heap_number_reg,
+ HeapNumber::kMantissaOffset));
+
+ __ mov(v0, heap_number_reg);
+ __ Ret();
+
+ __ bind(&slow_allocate_heapnumber);
+ Handle<Code> slow_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_Slow();
+ __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+
+ __ bind(&miss_force_generic);
+ Handle<Code> miss_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+ __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@@ -4292,6 +4361,126 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+ MacroAssembler* masm,
+ bool is_js_array) {
+ // ----------- S t a t e -------------
+ // -- a0 : value
+ // -- a1 : key
+ // -- a2 : receiver
+ // -- ra : return address
+ // -- a3 : scratch
+ // -- t0 : scratch (elements_reg)
+ // -- t1 : scratch (mantissa_reg)
+ // -- t2 : scratch (exponent_reg)
+ // -- t3 : scratch4
+ // -----------------------------------
+ Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
+
+ Register value_reg = a0;
+ Register key_reg = a1;
+ Register receiver_reg = a2;
+ Register scratch = a3;
+ Register elements_reg = t0;
+ Register mantissa_reg = t1;
+ Register exponent_reg = t2;
+ Register scratch4 = t3;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+ __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+ __ lw(elements_reg,
+ FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+ // Check that the key is within bounds.
+ if (is_js_array) {
+ __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+ } else {
+ __ lw(scratch,
+ FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+ }
+ // Compare smis, unsigned compare catches both negative and out-of-bound
+ // indexes.
+ __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
+
+ // Handle smi values specially.
+ __ JumpIfSmi(value_reg, &smi_value);
+
+ // Ensure that the object is a heap number
+ __ CheckMap(value_reg,
+ scratch,
+ masm->isolate()->factory()->heap_number_map(),
+ &miss_force_generic,
+ DONT_DO_SMI_CHECK);
+
+ // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
+ // in the exponent.
+ __ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
+ __ lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
+ __ Branch(&maybe_nan, ge, exponent_reg, Operand(scratch));
+
+ __ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+
+ __ bind(&have_double_value);
+ __ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize);
+ __ Addu(scratch, elements_reg, Operand(scratch4));
+ __ sw(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
+ uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+ __ sw(exponent_reg, FieldMemOperand(scratch, offset));
+ __ Ret();
+
+ __ bind(&maybe_nan);
+ // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+ // it's an Infinity, and the non-NaN code path applies.
+ __ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
+ __ Branch(&is_nan, gt, exponent_reg, Operand(scratch));
+ __ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+ __ Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
+
+ __ bind(&is_nan);
+ // Load canonical NaN for storing into the double array.
+ uint64_t nan_int64 = BitCast<uint64_t>(
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double());
+ __ li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
+ __ li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
+ __ jmp(&have_double_value);
+
+ __ bind(&smi_value);
+ __ Addu(scratch, elements_reg,
+ Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+ __ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize);
+ __ Addu(scratch, scratch, scratch4);
+ // scratch is now effective address of the double element
+
+ FloatingPointHelper::Destination destination;
+ if (CpuFeatures::IsSupported(FPU)) {
+ destination = FloatingPointHelper::kFPURegisters;
+ } else {
+ destination = FloatingPointHelper::kCoreRegisters;
+ }
+ __ SmiUntag(value_reg, value_reg);
+ FloatingPointHelper::ConvertIntToDouble(
+ masm, value_reg, destination,
+ f0, mantissa_reg, exponent_reg, // These are: double_dst, dst1, dst2.
+ scratch4, f2); // These are: scratch2, single_scratch.
+ if (destination == FloatingPointHelper::kFPURegisters) {
+ CpuFeatures::Scope scope(FPU);
+ __ sdc1(f0, MemOperand(scratch, 0));
+ } else {
+ __ sw(mantissa_reg, MemOperand(scratch, 0));
+ __ sw(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
+ }
+ __ Ret();
+
+ // Handle store cache miss, replacing the ic with the generic stub.
+ __ bind(&miss_force_generic);
+ Handle<Code> ic =
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
#undef __
} } // namespace v8::internal
diff --git a/deps/v8/src/mirror-debugger.js b/deps/v8/src/mirror-debugger.js
index 57de6c68f..bad08002d 100644
--- a/deps/v8/src/mirror-debugger.js
+++ b/deps/v8/src/mirror-debugger.js
@@ -1250,9 +1250,9 @@ const kFrameDetailsNameIndex = 0;
const kFrameDetailsValueIndex = 1;
const kFrameDetailsNameValueSize = 2;
-const kFrameDetailsFlagDebuggerFrame = 1;
-const kFrameDetailsFlagOptimizedFrame = 2;
-const kFrameDetailsFlagInlinedFrame = 4;
+const kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
+const kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
+const kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
/**
* Wrapper for the frame details information retreived from the VM. The frame
@@ -1266,7 +1266,7 @@ const kFrameDetailsFlagInlinedFrame = 4;
* 5: Source position
* 6: Construct call
* 7: Is at return
- * 8: Flags (debugger frame, optimized frame, inlined frame)
+ * 8: Flags (debugger frame, optimized frame, inlined frame index)
* Arguments name, value
* Locals name, value
* Return value if any
@@ -1312,22 +1312,27 @@ FrameDetails.prototype.isAtReturn = function() {
FrameDetails.prototype.isDebuggerFrame = function() {
%CheckExecutionState(this.break_id_);
- var f = kFrameDetailsFlagDebuggerFrame;
+ var f = kFrameDetailsFlagDebuggerFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
}
FrameDetails.prototype.isOptimizedFrame = function() {
%CheckExecutionState(this.break_id_);
- var f = kFrameDetailsFlagOptimizedFrame;
+ var f = kFrameDetailsFlagOptimizedFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
}
FrameDetails.prototype.isInlinedFrame = function() {
+ return this.inlinedFrameIndex() > 0;
+}
+
+
+FrameDetails.prototype.inlinedFrameIndex = function() {
%CheckExecutionState(this.break_id_);
- var f = kFrameDetailsFlagInlinedFrame;
- return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
+ var f = kFrameDetailsFlagInlinedFrameIndexMask;
+ return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2
}
@@ -1476,6 +1481,11 @@ FrameMirror.prototype.isInlinedFrame = function() {
};
+FrameMirror.prototype.inlinedFrameIndex = function() {
+ return this.details_.inlinedFrameIndex();
+};
+
+
FrameMirror.prototype.argumentCount = function() {
return this.details_.argumentCount();
};
@@ -1565,8 +1575,12 @@ FrameMirror.prototype.scope = function(index) {
FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
- var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
- source, Boolean(disable_break), opt_context_object);
+ var result = %DebugEvaluate(this.break_id_,
+ this.details_.frameId(),
+ this.details_.inlinedFrameIndex(),
+ source,
+ Boolean(disable_break),
+ opt_context_object);
return MakeMirror(result);
};
@@ -1591,8 +1605,10 @@ FrameMirror.prototype.invocationText = function() {
// Try to find the function as a property in the receiver. Include the
// prototype chain in the lookup.
var property = GetUndefinedMirror();
- if (!receiver.isUndefined()) {
- for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoObject()) {
+ if (receiver.isObject()) {
+ for (var r = receiver;
+ !r.isNull() && property.isUndefined();
+ r = r.protoObject()) {
property = r.lookupProperty(func);
}
}
@@ -1719,6 +1735,7 @@ function ScopeDetails(frame, index) {
this.break_id_ = frame.break_id_;
this.details_ = %GetScopeDetails(frame.break_id_,
frame.details_.frameId(),
+ frame.details_.inlinedFrameIndex(),
index);
}
diff --git a/deps/v8/src/natives.h b/deps/v8/src/natives.h
index a2831863a..5f34420d0 100644
--- a/deps/v8/src/natives.h
+++ b/deps/v8/src/natives.h
@@ -36,7 +36,7 @@ typedef bool (*NativeSourceCallback)(Vector<const char> name,
int index);
enum NativeType {
- CORE, EXPERIMENTAL, D8
+ CORE, EXPERIMENTAL, D8, TEST
};
template <NativeType type>
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
index 3d325b877..29632317a 100644
--- a/deps/v8/src/objects-debug.cc
+++ b/deps/v8/src/objects-debug.cc
@@ -315,7 +315,8 @@ void FixedDoubleArray::FixedDoubleArrayVerify() {
if (!is_the_hole(i)) {
double value = get(i);
ASSERT(!isnan(value) ||
- BitCast<uint64_t>(value) == kCanonicalNonHoleNanInt64);
+ (BitCast<uint64_t>(value) ==
+ BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())));
}
}
}
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index eb537c75a..5726b3739 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -1610,6 +1610,23 @@ void FixedArray::set(int index, Object* value) {
}
+inline bool FixedDoubleArray::is_the_hole_nan(double value) {
+ return BitCast<uint64_t, double>(value) == kHoleNanInt64;
+}
+
+
+inline double FixedDoubleArray::hole_nan_as_double() {
+ return BitCast<double, uint64_t>(kHoleNanInt64);
+}
+
+
+inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
+ ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
+ ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
+ return OS::nan_value();
+}
+
+
double FixedDoubleArray::get(int index) {
ASSERT(map() != HEAP->fixed_cow_array_map() &&
map() != HEAP->fixed_array_map());
@@ -3744,6 +3761,7 @@ void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
+ACCESSORS(JSProxy, padding, Object, kPaddingOffset)
Address Foreign::address() {
@@ -3989,7 +4007,8 @@ bool JSObject::HasIndexedInterceptor() {
bool JSObject::AllowsSetElementsLength() {
- bool result = elements()->IsFixedArray();
+ bool result = elements()->IsFixedArray() ||
+ elements()->IsFixedDoubleArray();
ASSERT(result == !HasExternalArrayElements());
return result;
}
@@ -4139,6 +4158,22 @@ Object* JSReceiver::GetPrototype() {
}
+bool JSReceiver::HasProperty(String* name) {
+ if (IsJSProxy()) {
+ return JSProxy::cast(this)->HasPropertyWithHandler(name);
+ }
+ return GetPropertyAttribute(name) != ABSENT;
+}
+
+
+bool JSReceiver::HasLocalProperty(String* name) {
+ if (IsJSProxy()) {
+ return JSProxy::cast(this)->HasPropertyWithHandler(name);
+ }
+ return GetLocalPropertyAttribute(name) != ABSENT;
+}
+
+
PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
return GetPropertyAttributeWithReceiver(this, key);
}
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index ca780dbe0..341f92975 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -58,11 +58,6 @@ namespace internal {
const int kGetterIndex = 0;
const int kSetterIndex = 1;
-uint64_t FixedDoubleArray::kHoleNanInt64 = -1;
-uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000;
-uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 =
- kCanonicalNonHoleNanLower32 << 32;
-
MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
Object* value) {
Object* result;
@@ -194,7 +189,7 @@ MaybeObject* Object::GetPropertyWithCallback(Object* receiver,
AccessorInfo* data = AccessorInfo::cast(structure);
Object* fun_obj = data->getter();
v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
- HandleScope scope;
+ HandleScope scope(isolate);
JSObject* self = JSObject::cast(receiver);
JSObject* holder_handle = JSObject::cast(holder);
Handle<String> key(name);
@@ -234,7 +229,7 @@ MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw,
String* name_raw,
Object* handler_raw) {
Isolate* isolate = name_raw->GetIsolate();
- HandleScope scope;
+ HandleScope scope(isolate);
Handle<Object> receiver(receiver_raw);
Handle<Object> name(name_raw);
Handle<Object> handler(handler_raw);
@@ -2178,9 +2173,9 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
}
}
- HandleScope scope;
- Handle<Object> value_handle(value);
Heap* heap = GetHeap();
+ HandleScope scope(heap->isolate());
+ Handle<Object> value_handle(value);
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
return *value_handle;
}
@@ -2201,13 +2196,38 @@ MaybeObject* JSReceiver::SetProperty(LookupResult* result,
}
+bool JSProxy::HasPropertyWithHandler(String* name_raw) {
+ Isolate* isolate = GetIsolate();
+ HandleScope scope(isolate);
+ Handle<Object> receiver(this);
+ Handle<Object> name(name_raw);
+ Handle<Object> handler(this->handler());
+
+ // Extract trap function.
+ Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("has");
+ Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
+ if (trap->IsUndefined()) {
+ trap = isolate->derived_has_trap();
+ }
+
+ // Call trap function.
+ Object** args[] = { name.location() };
+ bool has_exception;
+ Handle<Object> result =
+ Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
+ if (has_exception) return Failure::Exception();
+
+ return result->ToBoolean()->IsTrue();
+}
+
+
MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
String* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
Isolate* isolate = GetIsolate();
- HandleScope scope;
+ HandleScope scope(isolate);
Handle<Object> receiver(this);
Handle<Object> name(name_raw);
Handle<Object> value(value_raw);
@@ -2225,11 +2245,48 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
receiver.location(), name.location(), value.location()
};
bool has_exception;
+ Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
+ if (has_exception) return Failure::Exception();
+
+ return *value;
+}
+
+
+MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
+ String* name_raw, DeleteMode mode) {
+ Isolate* isolate = GetIsolate();
+ HandleScope scope(isolate);
+ Handle<Object> receiver(this);
+ Handle<Object> name(name_raw);
+ Handle<Object> handler(this->handler());
+
+ // Extract trap function.
+ Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
+ Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
+ if (trap->IsUndefined()) {
+ Handle<Object> args[] = { handler, trap_name };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
+ isolate->Throw(*error);
+ return Failure::Exception();
+ }
+
+ // Call trap function.
+ Object** args[] = { name.location() };
+ bool has_exception;
Handle<Object> result =
Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
if (has_exception) return Failure::Exception();
- return *value;
+ Object* bool_result = result->ToBoolean();
+ if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
+ Handle<Object> args[] = { handler, trap_name };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
+ isolate->Throw(*error);
+ return Failure::Exception();
+ }
+ return bool_result;
}
@@ -2238,7 +2295,7 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
String* name_raw,
bool* has_exception) {
Isolate* isolate = GetIsolate();
- HandleScope scope;
+ HandleScope scope(isolate);
Handle<JSReceiver> receiver(receiver_raw);
Handle<Object> name(name_raw);
Handle<Object> handler(this->handler());
@@ -2268,6 +2325,18 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
}
+void JSProxy::Fix() {
+ Isolate* isolate = GetIsolate();
+ HandleScope scope(isolate);
+ Handle<JSProxy> self(this);
+
+ isolate->factory()->BecomeJSObject(self);
+ ASSERT(IsJSObject());
+ // TODO(rossberg): recognize function proxies.
+}
+
+
+
MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
String* name,
Object* value,
@@ -2327,7 +2396,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
}
if (result->IsReadOnly() && result->IsProperty()) {
if (strict_mode == kStrictMode) {
- HandleScope scope;
+ HandleScope scope(heap->isolate());
Handle<String> key(name);
Handle<Object> holder(this);
Handle<Object> args[2] = { key, holder };
@@ -2811,16 +2880,18 @@ MaybeObject* JSObject::NormalizeElements() {
ASSERT(!HasExternalArrayElements());
// Find the backing store.
- FixedArray* array = FixedArray::cast(elements());
+ FixedArrayBase* array = FixedArrayBase::cast(elements());
Map* old_map = array->map();
bool is_arguments =
(old_map == old_map->heap()->non_strict_arguments_elements_map());
if (is_arguments) {
- array = FixedArray::cast(array->get(1));
+ array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
}
if (array->IsDictionary()) return array;
- ASSERT(HasFastElements() || HasFastArgumentsElements());
+ ASSERT(HasFastElements() ||
+ HasFastDoubleElements() ||
+ HasFastArgumentsElements());
// Compute the effective length and allocate a new backing store.
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
@@ -2833,7 +2904,7 @@ MaybeObject* JSObject::NormalizeElements() {
}
// Copy the elements to the new backing store.
- bool has_double_elements = old_map->has_fast_double_elements();
+ bool has_double_elements = array->IsFixedDoubleArray();
for (int i = 0; i < length; i++) {
Object* value = NULL;
if (has_double_elements) {
@@ -2851,7 +2922,7 @@ MaybeObject* JSObject::NormalizeElements() {
}
} else {
ASSERT(old_map->has_fast_elements());
- value = array->get(i);
+ value = FixedArray::cast(array)->get(i);
}
PropertyDetails details = PropertyDetails(NONE, NORMAL);
if (!value->IsTheHole()) {
@@ -3135,7 +3206,7 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
case FAST_DOUBLE_ELEMENTS: {
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
- : FixedArray::cast(elements())->length();
+ : FixedDoubleArray::cast(elements())->length();
if (index < static_cast<uint32_t>(length)) {
FixedDoubleArray::cast(elements())->set_the_hole(index);
}
@@ -3179,6 +3250,15 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
}
+MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
+ if (IsJSProxy()) {
+ return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
+ } else {
+ return JSObject::cast(this)->DeleteProperty(name, mode);
+ }
+}
+
+
MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
Isolate* isolate = GetIsolate();
// ECMA-262, 3rd, 8.6.2.5
@@ -7317,22 +7397,28 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
new_map = Map::cast(object);
}
- AssertNoAllocation no_gc;
- WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
switch (GetElementsKind()) {
- case FAST_ELEMENTS:
+ case FAST_ELEMENTS: {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
set_map(new_map);
set_elements(new_elements);
break;
- case DICTIONARY_ELEMENTS:
+ }
+ case DICTIONARY_ELEMENTS: {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
CopySlowElementsToFast(NumberDictionary::cast(elements()),
new_elements,
mode);
set_map(new_map);
set_elements(new_elements);
break;
+ }
case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
// The object's map and the parameter map are unchanged, the unaliased
// arguments are copied to the new backing store.
FixedArray* parameter_map = FixedArray::cast(elements());
@@ -7368,6 +7454,8 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
}
}
+ set_map(new_map);
+ set_elements(new_elements);
break;
}
case EXTERNAL_BYTE_ELEMENTS:
@@ -7430,7 +7518,9 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
break;
}
+ ASSERT(new_map->has_fast_double_elements());
set_map(new_map);
+ ASSERT(elems->IsFixedDoubleArray());
set_elements(elems);
if (IsJSArray()) {
@@ -7520,7 +7610,7 @@ void JSArray::Expand(int required_size) {
static Failure* ArrayLengthRangeError(Heap* heap) {
- HandleScope scope;
+ HandleScope scope(heap->isolate());
return heap->isolate()->Throw(
*FACTORY->NewRangeError("invalid_array_length",
HandleVector<Object>(NULL, 0)));
@@ -7536,32 +7626,57 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
const int value = Smi::cast(smi_length)->value();
if (value < 0) return ArrayLengthRangeError(GetHeap());
- switch (GetElementsKind()) {
- case FAST_ELEMENTS: {
- int old_capacity = FixedArray::cast(elements())->length();
+ JSObject::ElementsKind elements_kind = GetElementsKind();
+ switch (elements_kind) {
+ case FAST_ELEMENTS:
+ case FAST_DOUBLE_ELEMENTS: {
+ int old_capacity = FixedArrayBase::cast(elements())->length();
if (value <= old_capacity) {
if (IsJSArray()) {
Object* obj;
- { MaybeObject* maybe_obj = EnsureWritableFastElements();
+ if (elements_kind == FAST_ELEMENTS) {
+ MaybeObject* maybe_obj = EnsureWritableFastElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
- FixedArray* fast_elements = FixedArray::cast(elements());
if (2 * value <= old_capacity) {
// If more than half the elements won't be used, trim the array.
if (value == 0) {
initialize_elements();
} else {
- fast_elements->set_length(value);
- Address filler_start = fast_elements->address() +
- FixedArray::OffsetOfElementAt(value);
- int filler_size = (old_capacity - value) * kPointerSize;
+ Address filler_start;
+ int filler_size;
+ if (GetElementsKind() == FAST_ELEMENTS) {
+ FixedArray* fast_elements = FixedArray::cast(elements());
+ fast_elements->set_length(value);
+ filler_start = fast_elements->address() +
+ FixedArray::OffsetOfElementAt(value);
+ filler_size = (old_capacity - value) * kPointerSize;
+ } else {
+ ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
+ FixedDoubleArray* fast_double_elements =
+ FixedDoubleArray::cast(elements());
+ fast_double_elements->set_length(value);
+ filler_start = fast_double_elements->address() +
+ FixedDoubleArray::OffsetOfElementAt(value);
+ filler_size = (old_capacity - value) * kDoubleSize;
+ }
GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
}
} else {
// Otherwise, fill the unused tail with holes.
int old_length = FastD2I(JSArray::cast(this)->length()->Number());
- for (int i = value; i < old_length; i++) {
- fast_elements->set_the_hole(i);
+ if (GetElementsKind() == FAST_ELEMENTS) {
+ FixedArray* fast_elements = FixedArray::cast(elements());
+ for (int i = value; i < old_length; i++) {
+ fast_elements->set_the_hole(i);
+ }
+ } else {
+ ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
+ FixedDoubleArray* fast_double_elements =
+ FixedDoubleArray::cast(elements());
+ for (int i = value; i < old_length; i++) {
+ fast_double_elements->set_the_hole(i);
+ }
}
}
JSArray::cast(this)->set_length(Smi::cast(smi_length));
@@ -7572,8 +7687,14 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
int new_capacity = value > min ? value : min;
if (new_capacity <= kMaxFastElementsLength ||
!ShouldConvertToSlowElements(new_capacity)) {
- MaybeObject* result =
- SetFastElementsCapacityAndLength(new_capacity, value);
+ MaybeObject* result;
+ if (GetElementsKind() == FAST_ELEMENTS) {
+ result = SetFastElementsCapacityAndLength(new_capacity, value);
+ } else {
+ ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
+ result = SetFastDoubleElementsCapacityAndLength(new_capacity,
+ value);
+ }
if (result->IsFailure()) return result;
return this;
}
@@ -7609,7 +7730,6 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
UNREACHABLE();
break;
}
@@ -7718,7 +7838,7 @@ MaybeObject* JSReceiver::SetPrototype(Object* value,
// or [[Extensible]] must not violate the invariants defined in the preceding
// paragraph.
if (!this->map()->is_extensible()) {
- HandleScope scope;
+ HandleScope scope(heap->isolate());
Handle<Object> handle(this, heap->isolate());
return heap->isolate()->Throw(
*FACTORY->NewTypeError("non_extensible_proto",
@@ -7732,7 +7852,7 @@ MaybeObject* JSReceiver::SetPrototype(Object* value,
for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
if (JSObject::cast(pt) == this) {
// Cycle detected.
- HandleScope scope;
+ HandleScope scope(heap->isolate());
return heap->isolate()->Throw(
*FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
}
@@ -8022,6 +8142,15 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
!FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
break;
}
+ case FAST_DOUBLE_ELEMENTS: {
+ uint32_t length = IsJSArray() ?
+ static_cast<uint32_t>
+ (Smi::cast(JSArray::cast(this)->length())->value()) :
+ static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
+ if ((index < length) &&
+ !FixedDoubleArray::cast(elements())->is_the_hole(index)) return true;
+ break;
+ }
case EXTERNAL_PIXEL_ELEMENTS: {
ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
@@ -8043,9 +8172,6 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
}
break;
}
- case FAST_DOUBLE_ELEMENTS:
- UNREACHABLE();
- break;
case DICTIONARY_ELEMENTS: {
if (element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound) {
@@ -8407,8 +8533,9 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
} else {
new_length = dictionary->max_number_key() + 1;
}
- MaybeObject* result =
- SetFastElementsCapacityAndLength(new_length, new_length);
+ MaybeObject* result = ShouldConvertToFastDoubleElements()
+ ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
+ : SetFastElementsCapacityAndLength(new_length, new_length);
if (result->IsFailure()) return result;
#ifdef DEBUG
if (FLAG_trace_normalization) {
@@ -8495,6 +8622,9 @@ MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
}
// Otherwise default to slow case.
+ ASSERT(HasFastDoubleElements());
+ ASSERT(map()->has_fast_double_elements());
+ ASSERT(elements()->IsFixedDoubleArray());
Object* obj;
{ MaybeObject* maybe_obj = NormalizeElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@@ -8512,7 +8642,7 @@ MaybeObject* JSObject::SetElement(uint32_t index,
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
- HandleScope scope;
+ HandleScope scope(heap->isolate());
Handle<Object> value_handle(value);
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
return *value_handle;
@@ -8948,10 +9078,13 @@ bool JSObject::HasDenseElements() {
int capacity = 0;
int number_of_elements = 0;
- FixedArray* backing_store = FixedArray::cast(elements());
+ FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
+ FixedArray* backing_store = NULL;
switch (GetElementsKind()) {
case NON_STRICT_ARGUMENTS_ELEMENTS:
- backing_store = FixedArray::cast(backing_store->get(1));
+ backing_store_base =
+ FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
+ backing_store = FixedArray::cast(backing_store_base);
if (backing_store->IsDictionary()) {
NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
capacity = dictionary->Capacity();
@@ -8960,13 +9093,15 @@ bool JSObject::HasDenseElements() {
}
// Fall through.
case FAST_ELEMENTS:
+ backing_store = FixedArray::cast(backing_store_base);
capacity = backing_store->length();
for (int i = 0; i < capacity; ++i) {
if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
}
break;
case DICTIONARY_ELEMENTS: {
- NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
+ NumberDictionary* dictionary =
+ NumberDictionary::cast(FixedArray::cast(elements()));
capacity = dictionary->Capacity();
number_of_elements = dictionary->NumberOfElements();
break;
@@ -9474,6 +9609,21 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
ASSERT(!storage || storage->length() >= counter);
break;
}
+ case FAST_DOUBLE_ELEMENTS: {
+ int length = IsJSArray() ?
+ Smi::cast(JSArray::cast(this)->length())->value() :
+ FixedDoubleArray::cast(elements())->length();
+ for (int i = 0; i < length; i++) {
+ if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
+ if (storage != NULL) {
+ storage->set(counter, Smi::FromInt(i));
+ }
+ counter++;
+ }
+ }
+ ASSERT(!storage || storage->length() >= counter);
+ break;
+ }
case EXTERNAL_PIXEL_ELEMENTS: {
int length = ExternalPixelArray::cast(elements())->length();
while (counter < length) {
@@ -9503,9 +9653,6 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
ASSERT(!storage || storage->length() >= counter);
break;
}
- case FAST_DOUBLE_ELEMENTS:
- UNREACHABLE();
- break;
case DICTIONARY_ELEMENTS: {
if (storage != NULL) {
element_dictionary()->CopyKeysTo(storage,
@@ -11053,11 +11200,11 @@ void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
- JSObject::DeleteMode mode) {
+ JSReceiver::DeleteMode mode) {
Heap* heap = Dictionary<Shape, Key>::GetHeap();
PropertyDetails details = DetailsAt(entry);
// Ignore attributes if forcing a deletion.
- if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
+ if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
return heap->false_value();
}
SetEntry(entry, heap->null_value(), heap->null_value());
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 9765fe2a0..9b55ea747 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -1359,6 +1359,12 @@ class HeapNumber: public HeapObject {
// JSObject and JSProxy.
class JSReceiver: public HeapObject {
public:
+ enum DeleteMode {
+ NORMAL_DELETION,
+ STRICT_DELETION,
+ FORCE_DELETION
+ };
+
// Casting.
static inline JSReceiver* cast(Object* obj);
@@ -1373,6 +1379,8 @@ class JSReceiver: public HeapObject {
PropertyAttributes attributes,
StrictModeFlag strict_mode);
+ MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
+
// Returns the class name ([[Class]] property in the specification).
String* class_name();
@@ -1386,14 +1394,8 @@ class JSReceiver: public HeapObject {
PropertyAttributes GetLocalPropertyAttribute(String* name);
// Can cause a GC.
- bool HasProperty(String* name) {
- return GetPropertyAttribute(name) != ABSENT;
- }
-
- // Can cause a GC.
- bool HasLocalProperty(String* name) {
- return GetLocalPropertyAttribute(name) != ABSENT;
- }
+ inline bool HasProperty(String* name);
+ inline bool HasLocalProperty(String* name);
// Return the object's prototype (might be Heap::null_value()).
inline Object* GetPrototype();
@@ -1422,12 +1424,6 @@ class JSReceiver: public HeapObject {
// caching.
class JSObject: public JSReceiver {
public:
- enum DeleteMode {
- NORMAL_DELETION,
- STRICT_DELETION,
- FORCE_DELETION
- };
-
enum ElementsKind {
// The "fast" kind for tagged values. Must be first to make it possible
// to efficiently check maps if they have fast elements.
@@ -2173,23 +2169,12 @@ class FixedDoubleArray: public FixedArrayBase {
return kHeaderSize + length * kDoubleSize;
}
- // The following can't be declared inline as const static
- // because they're 64-bit.
- static uint64_t kCanonicalNonHoleNanLower32;
- static uint64_t kCanonicalNonHoleNanInt64;
- static uint64_t kHoleNanInt64;
-
- inline static bool is_the_hole_nan(double value) {
- return BitCast<uint64_t, double>(value) == kHoleNanInt64;
- }
-
- inline static double hole_nan_as_double() {
- return BitCast<double, uint64_t>(kHoleNanInt64);
- }
+ // Code Generation support.
+ static int OffsetOfElementAt(int index) { return SizeFor(index); }
- inline static double canonical_not_the_hole_nan_as_double() {
- return BitCast<double, uint64_t>(kCanonicalNonHoleNanInt64);
- }
+ inline static bool is_the_hole_nan(double value);
+ inline static double hole_nan_as_double();
+ inline static double canonical_not_the_hole_nan_as_double();
// Casting.
static inline FixedDoubleArray* cast(Object* obj);
@@ -6487,20 +6472,32 @@ class JSProxy: public JSReceiver {
// [handler]: The handler property.
DECL_ACCESSORS(handler, Object)
+ // [padding]: The padding slot (unused, see below).
+ DECL_ACCESSORS(padding, Object)
+
// Casting.
static inline JSProxy* cast(Object* obj);
+ bool HasPropertyWithHandler(String* name);
+
MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
- String* name_raw,
- Object* value_raw,
+ String* name,
+ Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
+ MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
+ String* name,
+ DeleteMode mode);
+
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
JSReceiver* receiver,
- String* name_raw,
+ String* name,
bool* has_exception);
+ // Turn this into an (empty) JSObject.
+ void Fix();
+
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSProxyPrint() {
@@ -6512,9 +6509,14 @@ class JSProxy: public JSReceiver {
void JSProxyVerify();
#endif
- // Layout description.
+ // Layout description. We add padding so that a proxy has the same
+ // size as a virgin JSObject. This is essential for becoming a JSObject
+ // upon freeze.
static const int kHandlerOffset = HeapObject::kHeaderSize;
- static const int kSize = kHandlerOffset + kPointerSize;
+ static const int kPaddingOffset = kHandlerOffset + kPointerSize;
+ static const int kSize = kPaddingOffset + kPointerSize;
+
+ STATIC_CHECK(kSize == JSObject::kHeaderSize);
typedef FixedBodyDescriptor<kHandlerOffset,
kHandlerOffset + kPointerSize,
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index 3085ef86b..5704cb805 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -648,6 +648,7 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
}
if (ok) {
result = new(zone()) FunctionLiteral(
+ isolate(),
no_name,
top_scope_,
body,
@@ -718,7 +719,6 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
{
// Parse the function literal.
- Handle<String> no_name = isolate()->factory()->empty_symbol();
Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
if (!info->closure().is_null()) {
scope = Scope::DeserializeScopeChain(info, scope);
@@ -1262,7 +1262,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// one must take great care not to treat it as a
// fall-through. It is much easier just to wrap the entire
// try-statement in a statement block and put the labels there
- Block* result = new(zone()) Block(labels, 1, false);
+ Block* result = new(zone()) Block(isolate(), labels, 1, false);
Target target(&this->target_stack_, result);
TryStatement* statement = ParseTryStatement(CHECK_OK);
if (statement) {
@@ -1453,10 +1453,10 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// introduced dynamically when we meet their declarations, whereas
// other functions are setup when entering the surrounding scope.
SharedFunctionInfoLiteral* lit =
- new(zone()) SharedFunctionInfoLiteral(shared);
+ new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
return new(zone()) ExpressionStatement(new(zone()) Assignment(
- Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+ isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
}
@@ -1489,7 +1489,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
// (ECMA-262, 3rd, 12.2)
//
// Construct block expecting 16 statements.
- Block* result = new(zone()) Block(labels, 16, false);
+ Block* result = new(zone()) Block(isolate(), labels, 16, false);
Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
@@ -1564,7 +1564,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// is inside an initializer block, it is ignored.
//
// Create new block with one expected declaration.
- Block* block = new(zone()) Block(NULL, 1, true);
+ Block* block = new(zone()) Block(isolate(), NULL, 1, true);
int nvars = 0; // the number of variables declared
Handle<String> name;
do {
@@ -1676,7 +1676,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// Compute the arguments for the runtime call.
ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
// We have at least 1 parameter.
- arguments->Add(new(zone()) Literal(name));
+ arguments->Add(NewLiteral(name));
CallRuntime* initialize;
if (is_const) {
@@ -1689,9 +1689,10 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// the number of arguments (1 or 2).
initialize =
new(zone()) CallRuntime(
- isolate()->factory()->InitializeConstGlobal_symbol(),
- Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
- arguments);
+ isolate(),
+ isolate()->factory()->InitializeConstGlobal_symbol(),
+ Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
+ arguments);
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
@@ -1715,9 +1716,10 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// the number of arguments (2 or 3).
initialize =
new(zone()) CallRuntime(
- isolate()->factory()->InitializeVarGlobal_symbol(),
- Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
- arguments);
+ isolate(),
+ isolate()->factory()->InitializeVarGlobal_symbol(),
+ Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
+ arguments);
}
block->AddStatement(new(zone()) ExpressionStatement(initialize));
@@ -1739,7 +1741,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
VariableProxy* proxy =
initialization_scope->NewUnresolved(name, in_with);
Assignment* assignment =
- new(zone()) Assignment(op, proxy, value, position);
+ new(zone()) Assignment(isolate(), op, proxy, value, position);
if (block) {
block->AddStatement(new(zone()) ExpressionStatement(assignment));
}
@@ -1842,7 +1844,8 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
} else {
else_statement = EmptyStatement();
}
- return new(zone()) IfStatement(condition, then_statement, else_statement);
+ return new(zone()) IfStatement(
+ isolate(), condition, then_statement, else_statement);
}
@@ -1961,17 +1964,17 @@ Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
// Create resulting block with two statements.
// 1: Evaluate the with expression.
// 2: The try-finally block evaluating the body.
- Block* result = new(zone()) Block(NULL, 2, false);
+ Block* result = new(zone()) Block(isolate(), NULL, 2, false);
if (result != NULL) {
result->AddStatement(new(zone()) EnterWithContextStatement(obj));
// Create body block.
- Block* body = new(zone()) Block(NULL, 1, false);
+ Block* body = new(zone()) Block(isolate(), NULL, 1, false);
body->AddStatement(stat);
// Create exit block.
- Block* exit = new(zone()) Block(NULL, 1, false);
+ Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
exit->AddStatement(new(zone()) ExitContextStatement());
// Return a try-finally statement.
@@ -2032,7 +2035,7 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
statements->Add(stat);
}
- return new(zone()) CaseClause(label, statements, pos);
+ return new(zone()) CaseClause(isolate(), label, statements, pos);
}
@@ -2041,7 +2044,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
- SwitchStatement* statement = new(zone()) SwitchStatement(labels);
+ SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
Target target(&this->target_stack_, statement);
Expect(Token::SWITCH, CHECK_OK);
@@ -2077,7 +2080,8 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
Expression* exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos));
+ return new(zone()) ExpressionStatement(
+ new(zone()) Throw(isolate(), exception, pos));
}
@@ -2156,7 +2160,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
}
// Create exit block.
- Block* inner_finally = new(zone()) Block(NULL, 1, false);
+ Block* inner_finally = new(zone()) Block(isolate(), NULL, 1, false);
inner_finally->AddStatement(new(zone()) ExitContextStatement());
// Create a try/finally statement.
@@ -2164,7 +2168,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
new(zone()) TryFinallyStatement(inner_body, inner_finally);
inner_try_finally->set_escaping_targets(inner_collector.targets());
- catch_block = new(zone()) Block(NULL, 1, false);
+ catch_block = new(zone()) Block(isolate(), NULL, 1, false);
catch_block->AddStatement(inner_try_finally);
} else {
Expect(Token::LBRACE, CHECK_OK);
@@ -2193,7 +2197,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
catch_variable,
catch_block);
statement->set_escaping_targets(try_collector.targets());
- try_block = new(zone()) Block(NULL, 1, false);
+ try_block = new(zone()) Block(isolate(), NULL, 1, false);
try_block->AddStatement(statement);
catch_block = NULL; // Clear to indicate it's been handled.
}
@@ -2224,7 +2228,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
- DoWhileStatement* loop = new(zone()) DoWhileStatement(labels);
+ DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
@@ -2255,7 +2259,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
- WhileStatement* loop = new(zone()) WhileStatement(labels);
+ WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::WHILE, CHECK_OK);
@@ -2285,7 +2289,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
if (peek() == Token::IN && !name.is_null()) {
VariableProxy* each = top_scope_->NewUnresolved(name, inside_with());
- ForInStatement* loop = new(zone()) ForInStatement(labels);
+ ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@@ -2294,7 +2298,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* body = ParseStatement(NULL, CHECK_OK);
loop->Initialize(each, enumerable, body);
- Block* result = new(zone()) Block(NULL, 2, false);
+ Block* result = new(zone()) Block(isolate(), NULL, 2, false);
result->AddStatement(variable_statement);
result->AddStatement(loop);
// Parsed for-in loop w/ variable/const declaration.
@@ -2315,7 +2319,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
isolate()->factory()->invalid_lhs_in_for_in_symbol();
expression = NewThrowReferenceError(type);
}
- ForInStatement* loop = new(zone()) ForInStatement(labels);
+ ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@@ -2334,7 +2338,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
}
// Standard 'for' loop
- ForStatement* loop = new(zone()) ForStatement(labels);
+ ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
// Parsed initializer at this point.
@@ -2370,7 +2374,8 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
Expect(Token::COMMA, CHECK_OK);
int position = scanner().location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- result = new(zone()) BinaryOperation(Token::COMMA, result, right, position);
+ result = new(zone()) BinaryOperation(
+ isolate(), Token::COMMA, result, right, position);
}
return result;
}
@@ -2442,7 +2447,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
fni_->Leave();
}
- return new(zone()) Assignment(op, expression, right, pos);
+ return new(zone()) Assignment(isolate(), op, expression, right, pos);
}
@@ -2464,8 +2469,8 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
Expect(Token::COLON, CHECK_OK);
int right_position = scanner().peek_location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- return new(zone()) Conditional(expression, left, right,
- left_position, right_position);
+ return new(zone()) Conditional(
+ isolate(), expression, left, right, left_position, right_position);
}
@@ -2552,12 +2557,12 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
x = NewCompareNode(cmp, x, y, position);
if (cmp != op) {
// The comparison was negated - add a NOT.
- x = new(zone()) UnaryOperation(Token::NOT, x, position);
+ x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
}
} else {
// We have a "normal" binary operation.
- x = new(zone()) BinaryOperation(op, x, y, position);
+ x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
}
}
}
@@ -2574,15 +2579,15 @@ Expression* Parser::NewCompareNode(Token::Value op,
bool is_strict = (op == Token::EQ_STRICT);
Literal* x_literal = x->AsLiteral();
if (x_literal != NULL && x_literal->IsNull()) {
- return new(zone()) CompareToNull(is_strict, y);
+ return new(zone()) CompareToNull(isolate(), is_strict, y);
}
Literal* y_literal = y->AsLiteral();
if (y_literal != NULL && y_literal->IsNull()) {
- return new(zone()) CompareToNull(is_strict, x);
+ return new(zone()) CompareToNull(isolate(), is_strict, x);
}
}
- return new(zone()) CompareOperation(op, x, y, position);
+ return new(zone()) CompareOperation(isolate(), op, x, y, position);
}
@@ -2611,7 +2616,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
// Convert the literal to a boolean condition and negate it.
bool condition = literal->ToBoolean()->IsTrue();
Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
- return new(zone()) Literal(result);
+ return NewLiteral(result);
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
double value = literal->Number();
@@ -2638,7 +2643,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
}
- return new(zone()) UnaryOperation(op, expression, position);
+ return new(zone()) UnaryOperation(isolate(), op, expression, position);
} else if (Token::IsCountOp(op)) {
op = Next();
@@ -2659,7 +2664,8 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
int position = scanner().location().beg_pos;
- return new(zone()) CountOperation(op,
+ return new(zone()) CountOperation(isolate(),
+ op,
true /* prefix */,
expression,
position);
@@ -2695,7 +2701,8 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
Token::Value next = Next();
int position = scanner().location().beg_pos;
expression =
- new(zone()) CountOperation(next,
+ new(zone()) CountOperation(isolate(),
+ next,
false /* postfix */,
expression,
position);
@@ -2721,7 +2728,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
- result = new(zone()) Property(result, index, pos);
+ result = new(zone()) Property(isolate(), result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
}
@@ -2759,7 +2766,10 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = new(zone()) Property(result, new(zone()) Literal(name), pos);
+ result = new(zone()) Property(isolate(),
+ result,
+ NewLiteral(name),
+ pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@@ -2795,7 +2805,8 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
if (!stack->is_empty()) {
int last = stack->pop();
- result = new(zone()) CallNew(result,
+ result = new(zone()) CallNew(isolate(),
+ result,
new(zone()) ZoneList<Expression*>(0),
last);
}
@@ -2843,7 +2854,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
- result = new(zone()) Property(result, index, pos);
+ result = new(zone()) Property(isolate(), result, index, pos);
if (fni_ != NULL) {
if (index->IsPropertyName()) {
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
@@ -2859,7 +2870,10 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = new(zone()) Property(result, new(zone()) Literal(name), pos);
+ result = new(zone()) Property(isolate(),
+ result,
+ NewLiteral(name),
+ pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@@ -2868,7 +2882,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
// Consume one of the new prefixes (already parsed).
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
int last = stack->pop();
- result = new CallNew(result, args, last);
+ result = new(zone()) CallNew(isolate(), result, args, last);
break;
}
default:
@@ -2952,23 +2966,26 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
switch (peek()) {
case Token::THIS: {
Consume(Token::THIS);
- result = new(zone()) VariableProxy(top_scope_->receiver());
+ result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
break;
}
case Token::NULL_LITERAL:
Consume(Token::NULL_LITERAL);
- result = new(zone()) Literal(isolate()->factory()->null_value());
+ result = new(zone()) Literal(
+ isolate(), isolate()->factory()->null_value());
break;
case Token::TRUE_LITERAL:
Consume(Token::TRUE_LITERAL);
- result = new(zone()) Literal(isolate()->factory()->true_value());
+ result = new(zone()) Literal(
+ isolate(), isolate()->factory()->true_value());
break;
case Token::FALSE_LITERAL:
Consume(Token::FALSE_LITERAL);
- result = new(zone()) Literal(isolate()->factory()->false_value());
+ result = new(zone()) Literal(
+ isolate(), isolate()->factory()->false_value());
break;
case Token::IDENTIFIER:
@@ -2994,7 +3011,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
case Token::STRING: {
Consume(Token::STRING);
Handle<String> symbol = GetSymbol(CHECK_OK);
- result = new(zone()) Literal(symbol);
+ result = NewLiteral(symbol);
if (fni_ != NULL) fni_->PushLiteralName(symbol);
break;
}
@@ -3121,8 +3138,8 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
literals->set_map(isolate()->heap()->fixed_cow_array_map());
}
- return new(zone()) ArrayLiteral(literals, values,
- literal_index, is_simple, depth);
+ return new(zone()) ArrayLiteral(
+ isolate(), literals, values, literal_index, is_simple, depth);
}
@@ -3425,7 +3442,6 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Expect(Token::LBRACE, CHECK_OK);
- Scanner::Location loc = scanner().location();
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
@@ -3467,7 +3483,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
// Failed to parse as get/set property, so it's just a property
// called "get" or "set".
- key = new(zone()) Literal(id);
+ key = NewLiteral(id);
break;
}
case Token::STRING: {
@@ -3479,7 +3495,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
key = NewNumberLiteral(index);
break;
}
- key = new(zone()) Literal(string);
+ key = NewLiteral(string);
break;
}
case Token::NUMBER: {
@@ -3495,7 +3511,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
if (Token::IsKeyword(next)) {
Consume(next);
Handle<String> string = GetSymbol(CHECK_OK);
- key = new(zone()) Literal(string);
+ key = NewLiteral(string);
} else {
// Unexpected token.
Token::Value next = Next();
@@ -3548,13 +3564,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
&is_simple,
&fast_elements,
&depth);
- return new(zone()) ObjectLiteral(constant_properties,
- properties,
- literal_index,
- is_simple,
- fast_elements,
- depth,
- has_function);
+ return new(zone()) ObjectLiteral(isolate(),
+ constant_properties,
+ properties,
+ literal_index,
+ is_simple,
+ fast_elements,
+ depth,
+ has_function);
}
@@ -3573,7 +3590,8 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Handle<String> js_flags = NextLiteralString(TENURED);
Next();
- return new(zone()) RegExpLiteral(js_pattern, js_flags, literal_index);
+ return new(zone()) RegExpLiteral(
+ isolate(), js_pattern, js_flags, literal_index);
}
@@ -3690,9 +3708,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
top_scope_->NewUnresolved(function_name, inside_with());
fproxy->BindTo(fvar);
body->Add(new(zone()) ExpressionStatement(
- new(zone()) Assignment(Token::INIT_CONST, fproxy,
- new(zone()) ThisFunction(),
- RelocInfo::kNoPosition)));
+ new(zone()) Assignment(isolate(),
+ Token::INIT_CONST,
+ fproxy,
+ new(zone()) ThisFunction(isolate()),
+ RelocInfo::kNoPosition)));
}
// Determine if the function will be lazily compiled. The mode can
@@ -3782,7 +3802,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
}
FunctionLiteral* function_literal =
- new(zone()) FunctionLiteral(name,
+ new(zone()) FunctionLiteral(isolate(),
+ name,
scope,
body,
materialized_literal_count,
@@ -3843,7 +3864,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
}
// We have a valid intrinsics call or a call to a builtin.
- return new(zone()) CallRuntime(name, function, args);
+ return new(zone()) CallRuntime(isolate(), name, function, args);
}
@@ -3899,12 +3920,12 @@ void Parser::ExpectSemicolon(bool* ok) {
Literal* Parser::GetLiteralUndefined() {
- return new(zone()) Literal(isolate()->factory()->undefined_value());
+ return NewLiteral(isolate()->factory()->undefined_value());
}
Literal* Parser::GetLiteralTheHole() {
- return new(zone()) Literal(isolate()->factory()->the_hole_value());
+ return NewLiteral(isolate()->factory()->the_hole_value());
}
@@ -4060,7 +4081,7 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
Literal* Parser::NewNumberLiteral(double number) {
- return new(zone()) Literal(isolate()->factory()->NewNumber(number, TENURED));
+ return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
}
@@ -4107,10 +4128,15 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
TENURED);
ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
- args->Add(new(zone()) Literal(type));
- args->Add(new(zone()) Literal(array));
- return new(zone()) Throw(new(zone()) CallRuntime(constructor, NULL, args),
- scanner().location().beg_pos);
+ args->Add(NewLiteral(type));
+ args->Add(NewLiteral(array));
+ CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
+ constructor,
+ NULL,
+ args);
+ return new(zone()) Throw(isolate(),
+ call_constructor,
+ scanner().location().beg_pos);
}
// ----------------------------------------------------------------------------
diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h
index 9ce1026c9..13a360358 100644
--- a/deps/v8/src/parser.h
+++ b/deps/v8/src/parser.h
@@ -668,9 +668,12 @@ class Parser {
Expression* NewCall(Expression* expression,
ZoneList<Expression*>* arguments,
int pos) {
- return new Call(expression, arguments, pos);
+ return new(zone()) Call(isolate(), expression, arguments, pos);
}
+ inline Literal* NewLiteral(Handle<Object> handle) {
+ return new(zone()) Literal(isolate(), handle);
+ }
// Create a number literal.
Literal* NewNumberLiteral(double value);
diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc
index ab22a79cd..bc280ea0a 100644
--- a/deps/v8/src/platform-linux.cc
+++ b/deps/v8/src/platform-linux.cc
@@ -734,6 +734,7 @@ class LinuxMutex : public Mutex {
ASSERT(result == 0);
result = pthread_mutex_init(&mutex_, &attrs);
ASSERT(result == 0);
+ USE(result);
}
virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); }
diff --git a/deps/v8/src/platform-nullos.cc b/deps/v8/src/platform-nullos.cc
index 08480ca80..8c2a8633d 100644
--- a/deps/v8/src/platform-nullos.cc
+++ b/deps/v8/src/platform-nullos.cc
@@ -217,6 +217,11 @@ void OS::Free(void* buf, const size_t length) {
}
+void OS::Guard(void* address, const size_t size) {
+ UNIMPLEMENTED();
+}
+
+
void OS::Sleep(int milliseconds) {
UNIMPLEMENTED();
}
diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc
index 5be305af9..deb4b7561 100644
--- a/deps/v8/src/platform-posix.cc
+++ b/deps/v8/src/platform-posix.cc
@@ -33,6 +33,7 @@
#include <errno.h>
#include <time.h>
+#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
@@ -43,6 +44,8 @@
#include <netinet/in.h>
#include <netdb.h>
+#undef MAP_TYPE
+
#if defined(ANDROID)
#define LOG_TAG "v8"
#include <utils/Log.h> // LOG_PRI_VA
@@ -67,6 +70,12 @@ intptr_t OS::MaxVirtualMemory() {
}
+// Create guard pages.
+void OS::Guard(void* address, const size_t size) {
+ mprotect(address, size, PROT_NONE);
+}
+
+
// ----------------------------------------------------------------------------
// Math functions
diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc
index 35b1a8ece..b23e25ec9 100644
--- a/deps/v8/src/platform-win32.cc
+++ b/deps/v8/src/platform-win32.cc
@@ -957,6 +957,12 @@ void OS::Free(void* address, const size_t size) {
}
+void OS::Guard(void* address, const size_t size) {
+ DWORD oldprotect;
+ VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect);
+}
+
+
void OS::Sleep(int milliseconds) {
::Sleep(milliseconds);
}
diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h
index c7fe984c4..4d7f9cf77 100644
--- a/deps/v8/src/platform.h
+++ b/deps/v8/src/platform.h
@@ -206,6 +206,10 @@ class OS {
size_t* allocated,
bool is_executable);
static void Free(void* address, const size_t size);
+
+ // Assign memory as a guard page so that access will cause an exception.
+ static void Guard(void* address, const size_t size);
+
// Get the Alignment guaranteed by Allocate().
static size_t AllocateAlignment();
diff --git a/deps/v8/src/rewriter.cc b/deps/v8/src/rewriter.cc
index 64d7b3684..e8ca5b9de 100644
--- a/deps/v8/src/rewriter.cc
+++ b/deps/v8/src/rewriter.cc
@@ -66,9 +66,13 @@ class Processor: public AstVisitor {
Expression* SetResult(Expression* value) {
result_assigned_ = true;
- VariableProxy* result_proxy = new VariableProxy(result_);
- return new Assignment(Token::ASSIGN, result_proxy, value,
- RelocInfo::kNoPosition);
+ Zone* zone = isolate()->zone();
+ VariableProxy* result_proxy = new(zone) VariableProxy(isolate(), result_);
+ return new(zone) Assignment(isolate(),
+ Token::ASSIGN,
+ result_proxy,
+ value,
+ RelocInfo::kNoPosition);
}
// Node visitors.
@@ -229,8 +233,10 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
if (processor.HasStackOverflow()) return false;
if (processor.result_assigned()) {
- VariableProxy* result_proxy = new VariableProxy(result);
- body->Add(new ReturnStatement(result_proxy));
+ Isolate* isolate = info->isolate();
+ Zone* zone = isolate->zone();
+ VariableProxy* result_proxy = new(zone) VariableProxy(isolate, result);
+ body->Add(new(zone) ReturnStatement(result_proxy));
}
}
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 56507aeb4..b4259c4a5 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -615,6 +615,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
+ ASSERT(args.length() == 1);
+ CONVERT_CHECKED(JSProxy, proxy, args[0]);
+ proxy->Fix();
+ return proxy;
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -3872,7 +3880,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
|| result.type() == CONSTANT_FUNCTION)) {
Object* ok;
{ MaybeObject* maybe_ok =
- obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
+ obj->DeleteProperty(name, JSReceiver::NORMAL_DELETION);
if (!maybe_ok->ToObject(&ok)) return maybe_ok;
}
}
@@ -4126,24 +4134,25 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
- Handle<JSObject> js_object,
+ Handle<JSReceiver> receiver,
Handle<Object> key) {
HandleScope scope(isolate);
// Check if the given key is an array index.
uint32_t index;
- if (key->ToArrayIndex(&index)) {
+ if (receiver->IsJSObject() && key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the
// characters of a string using [] notation. In the case of a
// String object we just need to redirect the deletion to the
// underlying string if the index is in range. Since the
// underlying string does nothing with the deletion, we can ignore
// such deletions.
- if (js_object->IsStringObjectWithCharacterAt(index)) {
+ if (receiver->IsStringObjectWithCharacterAt(index)) {
return isolate->heap()->true_value();
}
- return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
+ return JSObject::cast(*receiver)->DeleteElement(
+ index, JSReceiver::FORCE_DELETION);
}
Handle<String> key_string;
@@ -4158,7 +4167,7 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
}
key_string->TryFlatten();
- return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
+ return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
}
@@ -4237,12 +4246,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
- CONVERT_CHECKED(JSObject, object, args[0]);
+ CONVERT_CHECKED(JSReceiver, object, args[0]);
CONVERT_CHECKED(String, key, args[1]);
CONVERT_SMI_ARG_CHECKED(strict, 2);
return object->DeleteProperty(key, (strict == kStrictMode)
- ? JSObject::STRICT_DELETION
- : JSObject::NORMAL_DELETION);
+ ? JSReceiver::STRICT_DELETION
+ : JSReceiver::NORMAL_DELETION);
}
@@ -4306,11 +4315,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
- // Only JS objects can have properties.
- if (args[0]->IsJSObject()) {
- JSObject* object = JSObject::cast(args[0]);
+ // Only JS receivers can have properties.
+ if (args[0]->IsJSReceiver()) {
+ JSReceiver* receiver = JSReceiver::cast(args[0]);
CONVERT_CHECKED(String, key, args[1]);
- if (object->HasProperty(key)) return isolate->heap()->true_value();
+ if (receiver->HasProperty(key)) return isolate->heap()->true_value();
}
return isolate->heap()->false_value();
}
@@ -8198,9 +8207,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
// index is non-negative.
Handle<JSObject> object = Handle<JSObject>::cast(holder);
if (index >= 0) {
- return object->DeleteElement(index, JSObject::NORMAL_DELETION);
+ return object->DeleteElement(index, JSReceiver::NORMAL_DELETION);
} else {
- return object->DeleteProperty(*name, JSObject::NORMAL_DELETION);
+ return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
}
}
@@ -9976,6 +9985,71 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
}
+class FrameInspector {
+ public:
+ FrameInspector(JavaScriptFrame* frame,
+ int inlined_frame_index,
+ Isolate* isolate)
+ : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
+ // Calculate the deoptimized frame.
+ if (frame->is_optimized()) {
+ deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
+ frame, inlined_frame_index, isolate);
+ }
+ has_adapted_arguments_ = frame_->has_adapted_arguments();
+ is_optimized_ = frame_->is_optimized();
+ }
+
+ ~FrameInspector() {
+ // Get rid of the calculated deoptimized frame if any.
+ if (deoptimized_frame_ != NULL) {
+ Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
+ isolate_);
+ }
+ }
+
+ int GetParametersCount() {
+ return is_optimized_
+ ? deoptimized_frame_->parameters_count()
+ : frame_->ComputeParametersCount();
+ }
+ int expression_count() { return deoptimized_frame_->expression_count(); }
+ Object* GetFunction() {
+ return is_optimized_
+ ? deoptimized_frame_->GetFunction()
+ : frame_->function();
+ }
+ Object* GetParameter(int index) {
+ return is_optimized_
+ ? deoptimized_frame_->GetParameter(index)
+ : frame_->GetParameter(index);
+ }
+ Object* GetExpression(int index) {
+ return is_optimized_
+ ? deoptimized_frame_->GetExpression(index)
+ : frame_->GetExpression(index);
+ }
+
+ // To inspect all the provided arguments the frame might need to be
+ // replaced with the arguments frame.
+ void SetArgumentsFrame(JavaScriptFrame* frame) {
+ ASSERT(has_adapted_arguments_);
+ frame_ = frame;
+ is_optimized_ = frame_->is_optimized();
+ ASSERT(!is_optimized_);
+ }
+
+ private:
+ JavaScriptFrame* frame_;
+ DeoptimizedFrameInfo* deoptimized_frame_;
+ Isolate* isolate_;
+ bool is_optimized_;
+ bool has_adapted_arguments_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameInspector);
+};
+
+
static const int kFrameDetailsFrameIdIndex = 0;
static const int kFrameDetailsReceiverIndex = 1;
static const int kFrameDetailsFunctionIndex = 2;
@@ -10024,8 +10098,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
return heap->undefined_value();
}
- int deoptimized_frame_index = -1; // Frame index in optimized frame.
- DeoptimizedFrameInfo* deoptimized_frame = NULL;
+ int inlined_frame_index = 0; // Inlined frame index in optimized frame.
int count = 0;
JavaScriptFrameIterator it(isolate, id);
@@ -10036,13 +10109,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
if (it.done()) return heap->undefined_value();
if (it.frame()->is_optimized()) {
- deoptimized_frame_index =
+ inlined_frame_index =
it.frame()->GetInlineCount() - (index - count) - 1;
- deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
- it.frame(),
- deoptimized_frame_index,
- isolate);
}
+ FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
// Traverse the saved contexts chain to find the active context for the
// selected frame.
@@ -10061,12 +10131,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Check for constructor frame. Inlined frames cannot be construct calls.
bool inlined_frame =
- it.frame()->is_optimized() && deoptimized_frame_index != 0;
+ it.frame()->is_optimized() && inlined_frame_index != 0;
bool constructor = !inlined_frame && it.frame()->IsConstructor();
// Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
- Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
+ Handle<SharedFunctionInfo> shared(function->shared());
+ Handle<SerializedScopeInfo> scope_info(shared->scope_info());
ASSERT(*scope_info != SerializedScopeInfo::Empty());
ScopeInfo<> info(*scope_info);
@@ -10083,14 +10154,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
for (; i < info.number_of_stack_slots(); ++i) {
// Use the value from the stack.
locals->set(i * 2, *info.LocalName(i));
- if (it.frame()->is_optimized()) {
- // Get the value from the deoptimized frame.
- locals->set(i * 2 + 1,
- deoptimized_frame->GetExpression(i));
- } else {
- // Get the value from the stack.
- locals->set(i * 2 + 1, it.frame()->GetExpression(i));
- }
+ locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
}
if (i < info.NumberOfLocals()) {
// Get the context containing declarations.
@@ -10147,18 +10211,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same.
- it.AdvanceToArgumentsFrame();
+ if (it.frame()->has_adapted_arguments()) {
+ it.AdvanceToArgumentsFrame();
+ frame_inspector.SetArgumentsFrame(it.frame());
+ }
// Find the number of arguments to fill. At least fill the number of
// parameters for the function and fill more if more parameters are provided.
int argument_count = info.number_of_parameters();
+ if (argument_count < frame_inspector.GetParametersCount()) {
+ argument_count = frame_inspector.GetParametersCount();
+ }
+#ifdef DEBUG
if (it.frame()->is_optimized()) {
- ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
- } else {
- if (argument_count < it.frame()->ComputeParametersCount()) {
- argument_count = it.frame()->ComputeParametersCount();
- }
+ ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
}
+#endif
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
@@ -10170,13 +10238,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function (same as in function frame).
- if (it.frame()->is_optimized()) {
- // Get the function from the deoptimized frame.
- details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction());
- } else {
- // Get the function from the stack.
- details->set(kFrameDetailsFunctionIndex, it.frame()->function());
- }
+ details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
// Add the arguments count.
details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
@@ -10208,9 +10270,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
if (it.frame()->is_optimized()) {
flags |= 1 << 1;
- if (deoptimized_frame_index > 0) {
- flags |= 1 << 2;
- }
+ flags |= inlined_frame_index << 2;
}
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
@@ -10227,16 +10287,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
// Parameter value.
- if (it.frame()->is_optimized()) {
- // Get the value from the deoptimized frame.
- details->set(details_index++, deoptimized_frame->GetParameter(i));
+ if (i < it.frame()->ComputeParametersCount()) {
+ // Get the value from the stack.
+ details->set(details_index++, frame_inspector.GetParameter(i));
} else {
- if (i < it.frame()->ComputeParametersCount()) {
- // Get the value from the stack.
- details->set(details_index++, it.frame()->GetParameter(i));
- } else {
- details->set(details_index++, heap->undefined_value());
- }
+ details->set(details_index++, heap->undefined_value());
}
}
@@ -10254,10 +10309,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
// THE FRAME ITERATOR TO WRAP THE RECEIVER.
Handle<Object> receiver(it.frame()->receiver(), isolate);
- if (!receiver->IsJSObject()) {
- // If the receiver is NOT a JSObject we have hit an optimization
- // where a value object is not converted into a wrapped JS objects.
- // To hide this optimization from the debugger, we wrap the receiver
+ if (!receiver->IsJSObject() && !shared->strict_mode() && !shared->native()) {
+ // If the receiver is not a JSObject and the function is not a
+ // builtin or strict-mode we have hit an optimization where a
+ // value object is not converted into a wrapped JS objects. To
+ // hide this optimization from the debugger, we wrap the receiver
// by creating correct wrapper object based on the calling frame's
// global context.
it.Advance();
@@ -10268,12 +10324,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
details->set(kFrameDetailsReceiverIndex, *receiver);
- // Get rid of the calculated deoptimized frame if any.
- if (deoptimized_frame != NULL) {
- Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame,
- isolate);
- }
-
ASSERT_EQ(details_size, details_index);
return *isolate->factory()->NewJSArrayWithElements(details);
}
@@ -10309,12 +10359,15 @@ static bool CopyContextLocalsToScopeObject(
// Create a plain JSObject which materializes the local scope for the specified
// frame.
-static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
- JavaScriptFrame* frame) {
+static Handle<JSObject> MaterializeLocalScope(
+ Isolate* isolate,
+ JavaScriptFrame* frame,
+ int inlined_frame_index) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<SharedFunctionInfo> shared(function->shared());
Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
ScopeInfo<> scope_info(*serialized_scope_info);
+ FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
// Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function.
@@ -10327,7 +10380,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate,
SetProperty(local_scope,
scope_info.parameter_name(i),
- Handle<Object>(frame->GetParameter(i), isolate),
+ Handle<Object>(frame_inspector.GetParameter(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
@@ -10339,7 +10392,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate,
SetProperty(local_scope,
scope_info.stack_slot_name(i),
- Handle<Object>(frame->GetExpression(i), isolate),
+ Handle<Object>(frame_inspector.GetExpression(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
@@ -10459,9 +10512,12 @@ class ScopeIterator {
ScopeTypeCatch
};
- ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
+ ScopeIterator(Isolate* isolate,
+ JavaScriptFrame* frame,
+ int inlined_frame_index)
: isolate_(isolate),
frame_(frame),
+ inlined_frame_index_(inlined_frame_index),
function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())),
local_done_(false),
@@ -10546,7 +10602,7 @@ class ScopeIterator {
return Handle<JSObject>(CurrentContext()->global());
case ScopeIterator::ScopeTypeLocal:
// Materialize the content of the local scope into a JSObject.
- return MaterializeLocalScope(isolate_, frame_);
+ return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
case ScopeIterator::ScopeTypeWith:
// Return the with object.
return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
@@ -10626,6 +10682,7 @@ class ScopeIterator {
private:
Isolate* isolate_;
JavaScriptFrame* frame_;
+ int inlined_frame_index_;
Handle<JSFunction> function_;
Handle<Context> context_;
bool local_done_;
@@ -10654,7 +10711,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
// Count the visible scopes.
int n = 0;
- for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
+ for (ScopeIterator it(isolate, frame, 0);
+ !it.Done();
+ it.Next()) {
n++;
}
@@ -10669,14 +10728,15 @@ static const int kScopeDetailsSize = 2;
// Return an array with scope details
// args[0]: number: break id
// args[1]: number: frame index
-// args[2]: number: scope index
+// args[2]: number: inlined frame index
+// args[3]: number: scope index
//
// The array returned contains the following information:
// 0: Scope type
// 1: Scope object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
HandleScope scope(isolate);
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
// Check arguments.
Object* check;
@@ -10685,7 +10745,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (!maybe_check->ToObject(&check)) return maybe_check;
}
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
- CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
+ CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
+ CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
// Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id);
@@ -10694,7 +10755,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
// Find the requested scope.
int n = 0;
- ScopeIterator it(isolate, frame);
+ ScopeIterator it(isolate, frame, inlined_frame_index);
for (; !it.Done() && n < index; it.Next()) {
n++;
}
@@ -10724,7 +10785,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
// Print the scopes for the top frame.
StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
- for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
+ for (ScopeIterator it(isolate, frame, 0);
+ !it.Done();
+ it.Next()) {
it.DebugPrint();
}
#endif
@@ -11117,6 +11180,7 @@ static Handle<Context> CopyWithContextChain(Isolate* isolate,
// Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(Isolate* isolate,
JavaScriptFrame* frame,
+ int inlined_frame_index,
Handle<JSFunction> function,
Handle<SerializedScopeInfo> scope_info,
const ScopeInfo<>* sinfo,
@@ -11128,6 +11192,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
if (sinfo->number_of_stack_slots() > 0) {
index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
if (index != -1) {
+ CHECK(false);
return Handle<Object>(frame->GetExpression(index), isolate);
}
}
@@ -11140,7 +11205,9 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
}
}
- const int length = frame->ComputeParametersCount();
+ FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
+
+ int length = frame_inspector.GetParametersCount();
Handle<JSObject> arguments =
isolate->factory()->NewArgumentsObject(function, length);
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
@@ -11148,7 +11215,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) {
- array->set(i, frame->GetParameter(i), mode);
+ array->set(i, frame_inspector.GetParameter(i), mode);
}
arguments->set_elements(*array);
return arguments;
@@ -11175,7 +11242,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
// Check the execution state and decode arguments frame and source to be
// evaluated.
- ASSERT(args.length() == 5);
+ ASSERT(args.length() == 6);
Object* check_result;
{ MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args));
@@ -11184,9 +11251,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
}
}
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
- CONVERT_ARG_CHECKED(String, source, 2);
- CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
- Handle<Object> additional_context(args[4]);
+ CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
+ CONVERT_ARG_CHECKED(String, source, 3);
+ CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
+ Handle<Object> additional_context(args[5]);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
@@ -11226,7 +11294,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
#endif
// Materialize the content of the local scope into a JSObject.
- Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
+ Handle<JSObject> local_scope = MaterializeLocalScope(
+ isolate, frame, inlined_frame_index);
RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
// Allocate a new context for the debug evaluation and set the extension
@@ -11275,7 +11344,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
&has_pending_exception);
if (has_pending_exception) return Failure::Exception();
- Handle<Object> arguments = GetArgumentsObject(isolate, frame,
+ Handle<Object> arguments = GetArgumentsObject(isolate,
+ frame, inlined_frame_index,
function, scope_info,
&sinfo, function_context);
@@ -12214,8 +12284,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
// call to this function is encountered it is skipped. The seen_caller
// in/out parameter is used to remember if the caller has been seen
// yet.
-static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
- bool* seen_caller) {
+static bool ShowFrameInStackTrace(StackFrame* raw_frame,
+ Object* caller,
+ bool* seen_caller) {
// Only display JS frames.
if (!raw_frame->is_java_script())
return false;
@@ -12228,11 +12299,25 @@ static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
*seen_caller = true;
return false;
}
- // Skip all frames until we've seen the caller. Also, skip the most
- // obvious builtin calls. Some builtin calls (such as Number.ADD
- // which is invoked using 'call') are very difficult to recognize
- // so we're leaving them in for now.
- return *seen_caller && !frame->receiver()->IsJSBuiltinsObject();
+ // Skip all frames until we've seen the caller.
+ if (!(*seen_caller)) return false;
+ // Also, skip the most obvious builtin calls. We recognize builtins
+ // as (1) functions called with the builtins object as the receiver and
+ // as (2) functions from native scripts called with undefined as the
+ // receiver (direct calls to helper functions in the builtins
+ // code). Some builtin calls (such as Number.ADD which is invoked
+ // using 'call') are very difficult to recognize so we're leaving
+ // them in for now.
+ if (frame->receiver()->IsJSBuiltinsObject()) {
+ return false;
+ }
+ JSFunction* fun = JSFunction::cast(raw_fun);
+ Object* raw_script = fun->shared()->script();
+ if (frame->receiver()->IsUndefined() && raw_script->IsScript()) {
+ int script_type = Script::cast(raw_script)->type()->value();
+ return script_type != Script::TYPE_NATIVE;
+ }
+ return true;
}
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index e59c82cd6..ac912d812 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -284,6 +284,7 @@ namespace internal {
F(CreateJSProxy, 2, 1) \
F(IsJSProxy, 1, 1) \
F(GetHandler, 1, 1) \
+ F(Fix, 1, 1) \
\
/* Statements */ \
F(NewClosure, 3, 1) \
@@ -372,7 +373,7 @@ namespace internal {
F(GetFrameCount, 1, 1) \
F(GetFrameDetails, 2, 1) \
F(GetScopeCount, 2, 1) \
- F(GetScopeDetails, 3, 1) \
+ F(GetScopeDetails, 4, 1) \
F(DebugPrintScopes, 0, 1) \
F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \
@@ -385,7 +386,7 @@ namespace internal {
F(IsBreakOnException, 1, 1) \
F(PrepareStep, 3, 1) \
F(ClearStepping, 0, 1) \
- F(DebugEvaluate, 5, 1) \
+ F(DebugEvaluate, 6, 1) \
F(DebugEvaluateGlobal, 4, 1) \
F(DebugGetLoadedScripts, 0, 1) \
F(DebugReferencedBy, 3, 1) \
@@ -636,7 +637,7 @@ class Runtime : public AllStatic {
MUST_USE_RESULT static MaybeObject* ForceDeleteObjectProperty(
Isolate* isolate,
- Handle<JSObject> object,
+ Handle<JSReceiver> object,
Handle<Object> key);
MUST_USE_RESULT static MaybeObject* GetObjectProperty(
diff --git a/deps/v8/src/runtime.js b/deps/v8/src/runtime.js
index 77b97aed8..4b600df73 100644
--- a/deps/v8/src/runtime.js
+++ b/deps/v8/src/runtime.js
@@ -354,7 +354,8 @@ function IN(x) {
if (!IS_SPEC_OBJECT(x)) {
throw %MakeTypeError('invalid_in_operator_use', [this, x]);
}
- return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
+ return %_IsNonNegativeSmi(this) && !%IsJSProxy(x) ?
+ %HasElement(x, this) : %HasProperty(x, %ToString(this));
}
diff --git a/deps/v8/src/scopes.cc b/deps/v8/src/scopes.cc
index c6e2a4650..390a0b6e1 100644
--- a/deps/v8/src/scopes.cc
+++ b/deps/v8/src/scopes.cc
@@ -116,25 +116,27 @@ Variable* VariableMap::Lookup(Handle<String> name) {
// Dummy constructor
Scope::Scope(Type type)
- : inner_scopes_(0),
- variables_(false),
- temps_(0),
- params_(0),
- unresolved_(0),
- decls_(0),
- already_resolved_(false) {
+ : isolate_(Isolate::Current()),
+ inner_scopes_(0),
+ variables_(false),
+ temps_(0),
+ params_(0),
+ unresolved_(0),
+ decls_(0),
+ already_resolved_(false) {
SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
}
Scope::Scope(Scope* outer_scope, Type type)
- : inner_scopes_(4),
- variables_(),
- temps_(4),
- params_(4),
- unresolved_(16),
- decls_(4),
- already_resolved_(false) {
+ : isolate_(Isolate::Current()),
+ inner_scopes_(4),
+ variables_(),
+ temps_(4),
+ params_(4),
+ unresolved_(16),
+ decls_(4),
+ already_resolved_(false) {
SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
// At some point we might want to provide outer scopes to
// eval scopes (by walking the stack and reading the scope info).
@@ -145,13 +147,14 @@ Scope::Scope(Scope* outer_scope, Type type)
Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
- : inner_scopes_(4),
- variables_(),
- temps_(4),
- params_(4),
- unresolved_(16),
- decls_(4),
- already_resolved_(true) {
+ : isolate_(Isolate::Current()),
+ inner_scopes_(4),
+ variables_(),
+ temps_(4),
+ params_(4),
+ unresolved_(16),
+ decls_(4),
+ already_resolved_(true) {
ASSERT(!scope_info.is_null());
SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
if (scope_info->HasHeapAllocatedLocals()) {
@@ -162,7 +165,8 @@ Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
- : inner_scopes_(1),
+ : isolate_(Isolate::Current()),
+ inner_scopes_(1),
variables_(),
temps_(0),
params_(0),
@@ -186,7 +190,7 @@ void Scope::SetDefaults(Type type,
Handle<SerializedScopeInfo> scope_info) {
outer_scope_ = outer_scope;
type_ = type;
- scope_name_ = FACTORY->empty_symbol();
+ scope_name_ = isolate_->factory()->empty_symbol();
dynamics_ = NULL;
receiver_ = NULL;
function_ = NULL;
@@ -295,9 +299,12 @@ void Scope::Initialize(bool inside_with) {
receiver_ = outer_scope()->receiver();
} else {
Variable* var =
- variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
- false, Variable::THIS);
- var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
+ variables_.Declare(this,
+ isolate_->factory()->this_symbol(),
+ Variable::VAR,
+ false,
+ Variable::THIS);
+ var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1));
receiver_ = var;
}
@@ -305,8 +312,11 @@ void Scope::Initialize(bool inside_with) {
// Declare 'arguments' variable which exists in all functions.
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
- variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
- true, Variable::ARGUMENTS);
+ variables_.Declare(this,
+ isolate_->factory()->arguments_symbol(),
+ Variable::VAR,
+ true,
+ Variable::ARGUMENTS);
}
}
@@ -320,7 +330,7 @@ Variable* Scope::LocalLookup(Handle<String> name) {
//
// We should never lookup 'arguments' in this scope as it is implicitly
// present in every scope.
- ASSERT(*name != *FACTORY->arguments_symbol());
+ ASSERT(*name != *isolate_->factory()->arguments_symbol());
// There should be no local slot with the given name.
ASSERT(scope_info_->StackSlotIndex(*name) < 0);
@@ -340,7 +350,7 @@ Variable* Scope::LocalLookup(Handle<String> name) {
Variable* var =
variables_.Declare(this, name, mode, true, Variable::NORMAL);
- var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
+ var->set_rewrite(NewSlot(var, Slot::CONTEXT, index));
return var;
}
@@ -397,7 +407,8 @@ VariableProxy* Scope::NewUnresolved(Handle<String> name,
// the same name because they may be removed selectively via
// RemoveUnresolved().
ASSERT(!already_resolved());
- VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
+ VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
+ isolate_, name, false, inside_with, position);
unresolved_.Add(proxy);
return proxy;
}
@@ -697,7 +708,7 @@ Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
// Declare a new non-local.
var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
// Allocate it by giving it a dynamic lookup.
- var->set_rewrite(new Slot(var, Slot::LOOKUP, -1));
+ var->set_rewrite(NewSlot(var, Slot::LOOKUP, -1));
}
return var;
}
@@ -943,26 +954,28 @@ bool Scope::MustAllocateInContext(Variable* var) {
bool Scope::HasArgumentsParameter() {
for (int i = 0; i < params_.length(); i++) {
- if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol()))
+ if (params_[i]->name().is_identical_to(
+ isolate_->factory()->arguments_symbol())) {
return true;
+ }
}
return false;
}
void Scope::AllocateStackSlot(Variable* var) {
- var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
+ var->set_rewrite(NewSlot(var, Slot::LOCAL, num_stack_slots_++));
}
void Scope::AllocateHeapSlot(Variable* var) {
- var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
+ var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++));
}
void Scope::AllocateParameterLocals() {
ASSERT(is_function_scope());
- Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
+ Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol());
ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
bool uses_nonstrict_arguments = false;
@@ -1009,7 +1022,7 @@ void Scope::AllocateParameterLocals() {
} else {
ASSERT(var->rewrite() == NULL || var->IsParameter());
if (var->rewrite() == NULL) {
- var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
+ var->set_rewrite(NewSlot(var, Slot::PARAMETER, i));
}
}
}
@@ -1020,7 +1033,7 @@ void Scope::AllocateParameterLocals() {
void Scope::AllocateNonParameterLocal(Variable* var) {
ASSERT(var->scope() == this);
ASSERT(var->rewrite() == NULL ||
- !var->IsVariable(FACTORY->result_symbol()) ||
+ !var->IsVariable(isolate_->factory()->result_symbol()) ||
var->AsSlot() == NULL ||
var->AsSlot()->type() != Slot::LOCAL);
if (var->rewrite() == NULL && MustAllocate(var)) {
diff --git a/deps/v8/src/scopes.h b/deps/v8/src/scopes.h
index a493d5752..e76fb5059 100644
--- a/deps/v8/src/scopes.h
+++ b/deps/v8/src/scopes.h
@@ -319,6 +319,8 @@ class Scope: public ZoneObject {
explicit Scope(Type type);
+ Isolate* const isolate_;
+
// Scope tree.
Scope* outer_scope_; // the immediately enclosing outer scope, or NULL
ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes
@@ -423,6 +425,10 @@ class Scope: public ZoneObject {
// Construct a catch scope with a binding for the name.
Scope(Scope* inner_scope, Handle<String> catch_variable_name);
+ inline Slot* NewSlot(Variable* var, Slot::Type type, int index) {
+ return new(isolate_->zone()) Slot(isolate_, var, type, index);
+ }
+
void AddInnerScope(Scope* inner_scope) {
if (inner_scope != NULL) {
inner_scopes_.Add(inner_scope);
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc
index d41ce5589..0f80496b0 100644
--- a/deps/v8/src/spaces.cc
+++ b/deps/v8/src/spaces.cc
@@ -402,7 +402,9 @@ void MemoryAllocator::FreeRawMemory(void* mem,
size_t length,
Executability executable) {
#ifdef DEBUG
- ZapBlock(reinterpret_cast<Address>(mem), length);
+ // Do not try to zap the guard page.
+ size_t guard_size = (executable == EXECUTABLE) ? Page::kPageSize : 0;
+ ZapBlock(reinterpret_cast<Address>(mem) + guard_size, length - guard_size);
#endif
if (isolate_->code_range()->contains(static_cast<Address>(mem))) {
isolate_->code_range()->FreeRawMemory(mem, length);
@@ -504,14 +506,28 @@ Page* MemoryAllocator::AllocatePages(int requested_pages,
LOG(isolate_, NewEvent("PagedChunk", chunk, chunk_size));
*allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size);
+
// We may 'lose' a page due to alignment.
ASSERT(*allocated_pages >= kPagesPerChunk - 1);
- if (*allocated_pages == 0) {
- FreeRawMemory(chunk, chunk_size, owner->executable());
+
+ size_t guard_size = (owner->executable() == EXECUTABLE) ? Page::kPageSize : 0;
+
+ // Check that we got at least one page that we can use.
+ if (*allocated_pages <= ((guard_size != 0) ? 1 : 0)) {
+ FreeRawMemory(chunk,
+ chunk_size,
+ owner->executable());
LOG(isolate_, DeleteEvent("PagedChunk", chunk));
return Page::FromAddress(NULL);
}
+ if (guard_size != 0) {
+ OS::Guard(chunk, guard_size);
+ chunk_size -= guard_size;
+ chunk = static_cast<Address>(chunk) + guard_size;
+ --*allocated_pages;
+ }
+
int chunk_id = Pop();
chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner);
@@ -681,7 +697,8 @@ void MemoryAllocator::DeleteChunk(int chunk_id) {
LOG(isolate_, DeleteEvent("PagedChunk", c.address()));
ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner_identity());
size_t size = c.size();
- FreeRawMemory(c.address(), size, c.executable());
+ size_t guard_size = (c.executable() == EXECUTABLE) ? Page::kPageSize : 0;
+ FreeRawMemory(c.address() - guard_size, size + guard_size, c.executable());
PerformAllocationCallback(space, kAllocationActionFree, size);
}
c.init(NULL, 0, NULL);
@@ -2672,9 +2689,10 @@ LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes,
Executability executable) {
size_t requested = ChunkSizeFor(size_in_bytes);
size_t size;
+ size_t guard_size = (executable == EXECUTABLE) ? Page::kPageSize : 0;
Isolate* isolate = Isolate::Current();
void* mem = isolate->memory_allocator()->AllocateRawMemory(
- requested, &size, executable);
+ requested + guard_size, &size, executable);
if (mem == NULL) return NULL;
// The start of the chunk may be overlayed with a page so we have to
@@ -2682,13 +2700,19 @@ LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes,
ASSERT((size & Page::kPageFlagMask) == 0);
LOG(isolate, NewEvent("LargeObjectChunk", mem, size));
- if (size < requested) {
+ if (size < requested + guard_size) {
isolate->memory_allocator()->FreeRawMemory(
mem, size, executable);
LOG(isolate, DeleteEvent("LargeObjectChunk", mem));
return NULL;
}
+ if (guard_size != 0) {
+ OS::Guard(mem, guard_size);
+ size -= guard_size;
+ mem = static_cast<Address>(mem) + guard_size;
+ }
+
ObjectSpace space = (executable == EXECUTABLE)
? kObjectSpaceCodeSpace
: kObjectSpaceLoSpace;
@@ -2742,9 +2766,11 @@ void LargeObjectSpace::TearDown() {
ObjectSpace space = kObjectSpaceLoSpace;
if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
size_t size = chunk->size();
- heap()->isolate()->memory_allocator()->FreeRawMemory(chunk->address(),
- size,
- executable);
+ size_t guard_size = (executable == EXECUTABLE) ? Page::kPageSize : 0;
+ heap()->isolate()->memory_allocator()->FreeRawMemory(
+ chunk->address() - guard_size,
+ size + guard_size,
+ executable);
heap()->isolate()->memory_allocator()->PerformAllocationCallback(
space, kAllocationActionFree, size);
}
@@ -2941,10 +2967,15 @@ void LargeObjectSpace::FreeUnmarkedObjects() {
objects_size_ -= object->Size();
page_count_--;
ObjectSpace space = kObjectSpaceLoSpace;
- if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
- heap()->isolate()->memory_allocator()->FreeRawMemory(chunk_address,
- chunk_size,
- executable);
+ size_t guard_size = 0;
+ if (executable == EXECUTABLE) {
+ space = kObjectSpaceCodeSpace;
+ guard_size = Page::kPageSize;
+ }
+ heap()->isolate()->memory_allocator()->FreeRawMemory(
+ chunk_address - guard_size,
+ chunk_size + guard_size,
+ executable);
heap()->isolate()->memory_allocator()->PerformAllocationCallback(
space, kAllocationActionFree, size_);
LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk_address));
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
index c554a3777..ac5d99872 100644
--- a/deps/v8/src/spaces.h
+++ b/deps/v8/src/spaces.h
@@ -647,13 +647,11 @@ class MemoryAllocator {
#ifdef V8_TARGET_ARCH_X64
static const int kPagesPerChunk = 32;
// On 64 bit the chunk table consists of 4 levels of 4096-entry tables.
- static const int kPagesPerChunkLog2 = 5;
static const int kChunkTableLevels = 4;
static const int kChunkTableBitsPerLevel = 12;
#else
static const int kPagesPerChunk = 16;
// On 32 bit the chunk table consists of 2 levels of 256-entry tables.
- static const int kPagesPerChunkLog2 = 4;
static const int kChunkTableLevels = 2;
static const int kChunkTableBitsPerLevel = 8;
#endif
@@ -662,7 +660,6 @@ class MemoryAllocator {
MemoryAllocator();
static const int kChunkSize = kPagesPerChunk * Page::kPageSize;
- static const int kChunkSizeLog2 = kPagesPerChunkLog2 + kPageSizeBits;
// Maximum space size in bytes.
intptr_t capacity_;
diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h
index 93c50fa98..ffe4241ec 100644
--- a/deps/v8/src/stub-cache.h
+++ b/deps/v8/src/stub-cache.h
@@ -662,6 +662,8 @@ class KeyedLoadStubCompiler: public StubCompiler {
static void GenerateLoadFastElement(MacroAssembler* masm);
+ static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
+
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
private:
@@ -717,6 +719,9 @@ class KeyedStoreStubCompiler: public StubCompiler {
static void GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array);
+ static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
+ bool is_js_array);
+
static void GenerateStoreExternalArray(MacroAssembler* masm,
JSObject::ElementsKind elements_kind);
diff --git a/deps/v8/src/v8.cc b/deps/v8/src/v8.cc
index 11af057b1..36f835f00 100644
--- a/deps/v8/src/v8.cc
+++ b/deps/v8/src/v8.cc
@@ -50,6 +50,9 @@ bool V8::has_been_disposed_ = false;
bool V8::has_fatal_error_ = false;
bool V8::use_crankshaft_ = true;
+static Mutex* entropy_mutex = OS::CreateMutex();
+static EntropySource entropy_source;
+
bool V8::Initialize(Deserializer* des) {
InitializeOncePerProcess();
@@ -102,8 +105,14 @@ void V8::TearDown() {
static void seed_random(uint32_t* state) {
for (int i = 0; i < 2; ++i) {
- state[i] = FLAG_random_seed;
- while (state[i] == 0) {
+ if (FLAG_random_seed != 0) {
+ state[i] = FLAG_random_seed;
+ } else if (entropy_source != NULL) {
+ uint32_t val;
+ ScopedLock lock(entropy_mutex);
+ entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t));
+ state[i] = val;
+ } else {
state[i] = random();
}
}
@@ -124,6 +133,11 @@ static uint32_t random_base(uint32_t* state) {
}
+void V8::SetEntropySource(EntropySource source) {
+ entropy_source = source;
+}
+
+
// Used by JavaScript APIs
uint32_t V8::Random(Isolate* isolate) {
ASSERT(isolate == Isolate::Current());
diff --git a/deps/v8/src/v8.h b/deps/v8/src/v8.h
index e74a60c2f..e565ca5ae 100644
--- a/deps/v8/src/v8.h
+++ b/deps/v8/src/v8.h
@@ -91,6 +91,9 @@ class V8 : public AllStatic {
static void FatalProcessOutOfMemory(const char* location,
bool take_snapshot = false);
+ // Allows an entropy source to be provided for use in random number
+ // generation.
+ static void SetEntropySource(EntropySource source);
// Random number generation support. Not cryptographically safe.
static uint32_t Random(Isolate* isolate);
// We use random numbers internally in memory allocation and in the
diff --git a/deps/v8/src/v8globals.h b/deps/v8/src/v8globals.h
index d86f299f4..aff27579f 100644
--- a/deps/v8/src/v8globals.h
+++ b/deps/v8/src/v8globals.h
@@ -506,6 +506,16 @@ enum CallKind {
CALL_AS_FUNCTION
};
+
+static const uint32_t kHoleNanUpper32 = 0x7FFFFFFF;
+static const uint32_t kHoleNanLower32 = 0xFFFFFFFF;
+static const uint32_t kNaNOrInfinityLowerBoundUpper32 = 0x7FF00000;
+
+const uint64_t kHoleNanInt64 =
+ (static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
+const uint64_t kLastNonNaNInt64 =
+ (static_cast<uint64_t>(kNaNOrInfinityLowerBoundUpper32) << 32);
+
} } // namespace v8::internal
#endif // V8_V8GLOBALS_H_
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
index 53a03173b..984363586 100644
--- a/deps/v8/src/v8natives.js
+++ b/deps/v8/src/v8natives.js
@@ -663,7 +663,8 @@ function DefineProxyProperty(obj, p, attributes, should_throw) {
var result = %_CallFunction(handler, p, attributes, defineProperty);
if (!ToBoolean(result)) {
if (should_throw) {
- throw MakeTypeError("handler_failed", [handler, "defineProperty"]);
+ throw MakeTypeError("handler_returned_false",
+ [handler, "defineProperty"]);
} else {
return false;
}
@@ -1020,11 +1021,30 @@ function ObjectDefineProperties(obj, properties) {
}
+// Harmony proxies.
+function ProxyFix(obj) {
+ var handler = %GetHandler(obj);
+ var fix = handler.fix;
+ if (IS_UNDEFINED(fix)) {
+ throw MakeTypeError("handler_trap_missing", [handler, "fix"]);
+ }
+ var props = %_CallFunction(handler, fix);
+ if (IS_UNDEFINED(props)) {
+ throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
+ }
+ %Fix(obj);
+ ObjectDefineProperties(obj, props);
+}
+
+
// ES5 section 15.2.3.8.
function ObjectSeal(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
}
+ if (%IsJSProxy(obj)) {
+ ProxyFix(obj);
+ }
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@@ -1034,7 +1054,8 @@ function ObjectSeal(obj) {
DefineOwnProperty(obj, name, desc, true);
}
}
- return ObjectPreventExtension(obj);
+ %PreventExtensions(obj);
+ return obj;
}
@@ -1043,6 +1064,9 @@ function ObjectFreeze(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]);
}
+ if (%IsJSProxy(obj)) {
+ ProxyFix(obj);
+ }
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@@ -1053,7 +1077,8 @@ function ObjectFreeze(obj) {
DefineOwnProperty(obj, name, desc, true);
}
}
- return ObjectPreventExtension(obj);
+ %PreventExtensions(obj);
+ return obj;
}
@@ -1062,6 +1087,9 @@ function ObjectPreventExtension(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]);
}
+ if (%IsJSProxy(obj)) {
+ ProxyFix(obj);
+ }
%PreventExtensions(obj);
return obj;
}
@@ -1072,6 +1100,9 @@ function ObjectIsSealed(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["isSealed"]);
}
+ if (%IsJSProxy(obj)) {
+ return false;
+ }
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@@ -1090,6 +1121,9 @@ function ObjectIsFrozen(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["isFrozen"]);
}
+ if (%IsJSProxy(obj)) {
+ return false;
+ }
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@@ -1109,6 +1143,9 @@ function ObjectIsExtensible(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["isExtensible"]);
}
+ if (%IsJSProxy(obj)) {
+ return true;
+ }
return %IsExtensible(obj);
}
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index ee5411d88..b8ae21879 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 4
-#define BUILD_NUMBER 12
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 14
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/deps/v8/src/x64/assembler-x64.h b/deps/v8/src/x64/assembler-x64.h
index 4c1290414..c23eb1689 100644
--- a/deps/v8/src/x64/assembler-x64.h
+++ b/deps/v8/src/x64/assembler-x64.h
@@ -125,7 +125,7 @@ struct Register {
return names[index];
}
- static Register toRegister(int code) {
+ static Register from_code(int code) {
Register r = { code };
return r;
}
diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc
index 3cf7840d5..1a6efcbd6 100644
--- a/deps/v8/src/x64/code-stubs-x64.cc
+++ b/deps/v8/src/x64/code-stubs-x64.cc
@@ -2529,6 +2529,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
#else
// Already there in AMD64 calling convention.
ASSERT(arg1.is(rdi));
+ USE(arg1);
#endif
// Locate the code entry and call it.
@@ -3198,6 +3199,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor =
Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
+ __ SetCallKind(rcx, CALL_AS_METHOD);
__ Jump(adaptor, RelocInfo::CODE_TARGET);
}
diff --git a/deps/v8/src/x64/deoptimizer-x64.cc b/deps/v8/src/x64/deoptimizer-x64.cc
index 7eb08f7e0..2a31f28d5 100644
--- a/deps/v8/src/x64/deoptimizer-x64.cc
+++ b/deps/v8/src/x64/deoptimizer-x64.cc
@@ -128,7 +128,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
Address instruction_start = function->code()->instruction_start();
Address jump_table_address =
instruction_start + function->code()->safepoint_table_offset();
+#ifdef DEBUG
Address previous_pc = instruction_start;
+#endif
SafepointTableDeoptimiztionEntryIterator deoptimizations(function->code());
Address entry_pc = NULL;
@@ -157,12 +159,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
CodePatcher patcher(call_address, Assembler::kCallInstructionLength);
patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY),
RelocInfo::NONE);
+#ifdef DEBUG
previous_pc = call_end_address;
+#endif
} else {
// Not room enough for a long Call instruction. Write a short call
// instruction to a long jump placed elsewhere in the code.
+#ifdef DEBUG
Address short_call_end_address =
call_address + MacroAssembler::kShortCallInstructionLength;
+#endif
ASSERT(next_pc >= short_call_end_address);
// Write jump in jump-table.
@@ -177,7 +183,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
CodePatcher call_patcher(call_address,
MacroAssembler::kShortCallInstructionLength);
call_patcher.masm()->call(jump_table_address);
+#ifdef DEBUG
previous_pc = short_call_end_address;
+#endif
}
// Continue with next deoptimization entry.
@@ -643,7 +651,7 @@ void Deoptimizer::EntryGenerator::Generate() {
// We push all registers onto the stack, even though we do not need
// to restore all later.
for (int i = 0; i < kNumberOfRegisters; i++) {
- Register r = Register::toRegister(i);
+ Register r = Register::from_code(i);
__ push(r);
}
@@ -801,12 +809,12 @@ void Deoptimizer::EntryGenerator::Generate() {
// Restore the registers from the stack.
for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) {
- Register r = Register::toRegister(i);
+ Register r = Register::from_code(i);
// Do not restore rsp, simply pop the value into the next register
// and overwrite this afterwards.
if (r.is(rsp)) {
ASSERT(i > 0);
- r = Register::toRegister(i - 1);
+ r = Register::from_code(i - 1);
}
__ pop(r);
}
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index a54bff59b..0f7e5b3d7 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -4060,10 +4060,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
default: {
VisitForAccumulatorValue(expr->right());
Condition cc = no_condition;
- bool strict = false;
switch (op) {
case Token::EQ_STRICT:
- strict = true;
// Fall through.
case Token::EQ:
cc = equal;
diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc
index 98667ce87..49361e4f3 100644
--- a/deps/v8/src/x64/lithium-codegen-x64.cc
+++ b/deps/v8/src/x64/lithium-codegen-x64.cc
@@ -1883,7 +1883,6 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
__ push(ToRegister(instr->InputAt(0)));
__ Push(instr->function());
- Register temp = ToRegister(instr->TempAt(0));
static const int kAdditionalDelta = 10;
int delta =
masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
@@ -2245,10 +2244,35 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
}
-Operand LCodeGen::BuildExternalArrayOperand(
+void LCodeGen::DoLoadKeyedFastDoubleElement(
+ LLoadKeyedFastDoubleElement* instr) {
+ Register elements = ToRegister(instr->elements());
+ XMMRegister result(ToDoubleRegister(instr->result()));
+
+ if (instr->hydrogen()->RequiresHoleCheck()) {
+ int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
+ sizeof(kHoleNanLower32);
+ Operand hole_check_operand = BuildFastArrayOperand(
+ instr->elements(),
+ instr->key(),
+ JSObject::FAST_DOUBLE_ELEMENTS,
+ offset);
+ __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
+ DeoptimizeIf(equal, instr->environment());
+ }
+
+ Operand double_load_operand = BuildFastArrayOperand(
+ instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+ __ movsd(result, double_load_operand);
+}
+
+
+Operand LCodeGen::BuildFastArrayOperand(
LOperand* external_pointer,
LOperand* key,
- JSObject::ElementsKind elements_kind) {
+ JSObject::ElementsKind elements_kind,
+ uint32_t offset) {
Register external_pointer_reg = ToRegister(external_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
if (key->IsConstantOperand()) {
@@ -2256,10 +2280,12 @@ Operand LCodeGen::BuildExternalArrayOperand(
if (constant_value & 0xF0000000) {
Abort("array index constant value too big");
}
- return Operand(external_pointer_reg, constant_value * (1 << shift_size));
+ return Operand(external_pointer_reg,
+ constant_value * (1 << shift_size) + offset);
} else {
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
- return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
+ return Operand(external_pointer_reg, ToRegister(key),
+ scale_factor, offset);
}
}
@@ -2267,8 +2293,8 @@ Operand LCodeGen::BuildExternalArrayOperand(
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
- Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
- instr->key(), elements_kind));
+ Operand operand(BuildFastArrayOperand(instr->external_pointer(),
+ instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
@@ -2994,8 +3020,8 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
- Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
- instr->key(), elements_kind));
+ Operand operand(BuildFastArrayOperand(instr->external_pointer(),
+ instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister value(ToDoubleRegister(instr->value()));
__ cvtsd2ss(value, value);
@@ -3072,6 +3098,28 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
}
+void LCodeGen::DoStoreKeyedFastDoubleElement(
+ LStoreKeyedFastDoubleElement* instr) {
+ XMMRegister value = ToDoubleRegister(instr->value());
+ Register elements = ToRegister(instr->elements());
+ Label have_value;
+
+ __ ucomisd(value, value);
+ __ j(parity_odd, &have_value); // NaN.
+
+ ExternalReference canonical_nan_reference =
+ ExternalReference::address_of_canonical_non_hole_nan();
+ __ Set(kScratchRegister, BitCast<uint64_t>(
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
+ __ movq(value, kScratchRegister);
+
+ __ bind(&have_value);
+ Operand double_store_operand = BuildFastArrayOperand(
+ instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag);
+ __ movsd(double_store_operand, value);
+}
+
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(rdx));
ASSERT(ToRegister(instr->key()).is(rcx));
diff --git a/deps/v8/src/x64/lithium-codegen-x64.h b/deps/v8/src/x64/lithium-codegen-x64.h
index feacc2c82..d7c72b544 100644
--- a/deps/v8/src/x64/lithium-codegen-x64.h
+++ b/deps/v8/src/x64/lithium-codegen-x64.h
@@ -215,10 +215,11 @@ class LCodeGen BASE_EMBEDDED {
Register ToRegister(int index) const;
XMMRegister ToDoubleRegister(int index) const;
- Operand BuildExternalArrayOperand(
+ Operand BuildFastArrayOperand(
LOperand* external_pointer,
LOperand* key,
- JSObject::ElementsKind elements_kind);
+ JSObject::ElementsKind elements_kind,
+ uint32_t offset);
// Specific math operations - used from DoUnaryMathOperation.
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc
index b2994cd15..5b502a80c 100644
--- a/deps/v8/src/x64/lithium-x64.cc
+++ b/deps/v8/src/x64/lithium-x64.cc
@@ -428,6 +428,15 @@ void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
+void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+ elements()->PrintTo(stream);
+ stream->Add("[");
+ key()->PrintTo(stream);
+ stream->Add("] <- ");
+ value()->PrintTo(stream);
+}
+
+
void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add("[");
@@ -1822,6 +1831,18 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
}
+LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
+ HLoadKeyedFastDoubleElement* instr) {
+ ASSERT(instr->representation().IsDouble());
+ ASSERT(instr->key()->representation().IsInteger32());
+ LOperand* elements = UseRegisterAtStart(instr->elements());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+ LLoadKeyedFastDoubleElement* result =
+ new LLoadKeyedFastDoubleElement(elements, key);
+ return AssignEnvironment(DefineAsRegister(result));
+}
+
+
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
@@ -1874,6 +1895,20 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
}
+LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
+ HStoreKeyedFastDoubleElement* instr) {
+ ASSERT(instr->value()->representation().IsDouble());
+ ASSERT(instr->elements()->representation().IsTagged());
+ ASSERT(instr->key()->representation().IsInteger32());
+
+ LOperand* elements = UseRegisterAtStart(instr->elements());
+ LOperand* val = UseTempRegister(instr->value());
+ LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+
+ return new LStoreKeyedFastDoubleElement(elements, key, val);
+}
+
+
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());
diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h
index af0b29991..12bdfb28a 100644
--- a/deps/v8/src/x64/lithium-x64.h
+++ b/deps/v8/src/x64/lithium-x64.h
@@ -121,6 +121,7 @@ class LCodeGen;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
+ V(LoadKeyedFastDoubleElement) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
@@ -147,6 +148,7 @@ class LCodeGen;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
+ V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@@ -1134,6 +1136,22 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
+class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
+ inputs_[0] = elements;
+ inputs_[1] = key;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
+ "load-keyed-fast-double-element")
+ DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
+
+ LOperand* elements() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+};
+
+
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
@@ -1585,6 +1603,28 @@ class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
};
+class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+ LStoreKeyedFastDoubleElement(LOperand* elements,
+ LOperand* key,
+ LOperand* val) {
+ inputs_[0] = elements;
+ inputs_[1] = key;
+ inputs_[2] = val;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
+ "store-keyed-fast-double-element")
+ DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ LOperand* elements() { return inputs_[0]; }
+ LOperand* key() { return inputs_[1]; }
+ LOperand* value() { return inputs_[2]; }
+};
+
+
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index 1df022843..2b15553f1 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -385,6 +385,9 @@ void MacroAssembler::AssertFastElements(Register elements) {
Heap::kFixedArrayMapRootIndex);
j(equal, &ok, Label::kNear);
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+ Heap::kFixedDoubleArrayMapRootIndex);
+ j(equal, &ok, Label::kNear);
+ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
Heap::kFixedCOWArrayMapRootIndex);
j(equal, &ok, Label::kNear);
Abort("JSObject with fast elements map has slow elements");
diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.cc b/deps/v8/src/x64/regexp-macro-assembler-x64.cc
index 2ea17f0e9..395466e77 100644
--- a/deps/v8/src/x64/regexp-macro-assembler-x64.cc
+++ b/deps/v8/src/x64/regexp-macro-assembler-x64.cc
@@ -661,7 +661,6 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
}
__ movq(rbx, ExternalReference::re_word_character_map());
ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
- ExternalReference word_map = ExternalReference::re_word_character_map();
__ testb(Operand(rbx, current_character(), times_1, 0),
current_character());
BranchOrBacktrack(zero, on_no_match);
@@ -676,7 +675,6 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
}
__ movq(rbx, ExternalReference::re_word_character_map());
ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
- ExternalReference word_map = ExternalReference::re_word_character_map();
__ testb(Operand(rbx, current_character(), times_1, 0),
current_character());
BranchOrBacktrack(not_zero, on_no_match);
diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc
index 71ce85616..b8e5f22ed 100644
--- a/deps/v8/src/x64/stub-cache-x64.cc
+++ b/deps/v8/src/x64/stub-cache-x64.cc
@@ -1089,9 +1089,8 @@ void StubCompiler::GenerateLoadConstant(JSObject* object,
__ JumpIfSmi(receiver, miss);
// Check that the maps haven't changed.
- Register reg =
- CheckPrototypes(object, receiver, holder,
- scratch1, scratch2, scratch3, name, miss);
+ CheckPrototypes(object, receiver, holder,
+ scratch1, scratch2, scratch3, name, miss);
// Return the constant value.
__ Move(rax, Handle<Object>(value));
@@ -3584,6 +3583,57 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+ MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss_force_generic, slow_allocate_heapnumber;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(rax, &miss_force_generic);
+
+ // Get the elements array.
+ __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ AssertFastElements(rcx);
+
+ // Check that the key is within bounds.
+ __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
+ __ j(above_equal, &miss_force_generic);
+
+ // Check for the hole
+ __ SmiToInteger32(kScratchRegister, rax);
+ uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+ __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset),
+ Immediate(kHoleNanUpper32));
+ __ j(equal, &miss_force_generic);
+
+ // Always allocate a heap number for the result.
+ __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8,
+ FixedDoubleArray::kHeaderSize));
+ __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
+ // Set the value.
+ __ movq(rax, rcx);
+ __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
+ __ ret(0);
+
+ __ bind(&slow_allocate_heapnumber);
+ Handle<Code> slow_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_Slow();
+ __ jmp(slow_ic, RelocInfo::CODE_TARGET);
+
+ __ bind(&miss_force_generic);
+ Handle<Code> miss_ic =
+ masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+ __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@@ -3634,6 +3684,90 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+ MacroAssembler* masm,
+ bool is_js_array) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss_force_generic, smi_value, is_nan, maybe_nan;
+ Label have_double_value, not_nan;
+
+ // This stub is meant to be tail-jumped to, the receiver must already
+ // have been verified by the caller to not be a smi.
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(rcx, &miss_force_generic);
+
+ // Get the elements array.
+ __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ AssertFastElements(rdi);
+
+ // Check that the key is within bounds.
+ if (is_js_array) {
+ __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
+ } else {
+ __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
+ }
+ __ j(above_equal, &miss_force_generic);
+
+ // Handle smi values specially
+ __ JumpIfSmi(rax, &smi_value, Label::kNear);
+
+ __ CheckMap(rax,
+ masm->isolate()->factory()->heap_number_map(),
+ &miss_force_generic,
+ DONT_DO_SMI_CHECK);
+
+ // Double value, canonicalize NaN.
+ uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
+ __ cmpl(FieldOperand(rax, offset),
+ Immediate(kNaNOrInfinityLowerBoundUpper32));
+ __ j(greater_equal, &maybe_nan, Label::kNear);
+
+ __ bind(&not_nan);
+ __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
+ __ bind(&have_double_value);
+ __ SmiToInteger32(rcx, rcx);
+ __ movsd(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize),
+ xmm0);
+ __ ret(0);
+
+ __ bind(&maybe_nan);
+ // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+ // it's an Infinity, and the non-NaN code path applies.
+ __ j(greater, &is_nan, Label::kNear);
+ __ cmpl(FieldOperand(rax, HeapNumber::kValueOffset), Immediate(0));
+ __ j(zero, &not_nan);
+ __ bind(&is_nan);
+ // Convert all NaNs to the same canonical NaN value when they are stored in
+ // the double array.
+ __ Set(kScratchRegister, BitCast<uint64_t>(
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
+ __ movq(xmm0, kScratchRegister);
+ __ jmp(&have_double_value, Label::kNear);
+
+ __ bind(&smi_value);
+ // Value is a smi. convert to a double and store.
+ __ SmiToInteger32(rax, rax);
+ __ push(rax);
+ __ fild_s(Operand(rsp, 0));
+ __ pop(rax);
+ __ SmiToInteger32(rcx, rcx);
+ __ fstp_d(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize));
+ __ ret(0);
+
+ // Handle store cache miss, replacing the ic with the generic stub.
+ __ bind(&miss_force_generic);
+ Handle<Code> ic_force_generic =
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+ __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+}
+
+
#undef __
} } // namespace v8::internal
diff --git a/deps/v8/src/zone.h b/deps/v8/src/zone.h
index af9c916d7..abb53ad46 100644
--- a/deps/v8/src/zone.h
+++ b/deps/v8/src/zone.h
@@ -74,6 +74,8 @@ class Zone {
inline void adjust_segment_bytes_allocated(int delta);
+ inline Isolate* isolate() { return isolate_; }
+
static unsigned allocation_size_;
private:
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
index 0ef5667ab..b0a71664c 100644
--- a/deps/v8/test/cctest/SConscript
+++ b/deps/v8/test/cctest/SConscript
@@ -29,9 +29,23 @@ import sys
from os.path import join, dirname, abspath
root_dir = dirname(File('SConstruct').rfile().abspath)
sys.path.append(join(root_dir, 'tools'))
+import js2c
Import('context object_files tools')
+# Needed for test-log. Paths are relative to the cctest dir.
+JS_FILES_FOR_TESTS = [
+ '../../../tools/splaytree.js',
+ '../../../tools/codemap.js',
+ '../../../tools/csvparser.js',
+ '../../../tools/consarray.js',
+ '../../../tools/profile.js',
+ '../../../tools/profile_view.js',
+ '../../../tools/logreader.js',
+ 'log-eq-of-logging-and-traversal.js',
+]
+
+
SOURCES = {
'all': [
'gay-fixed.cc',
@@ -109,9 +123,19 @@ def Build():
env = Environment(tools=tools)
env.Replace(**context.flags['cctest'])
context.ApplyEnvOverrides(env)
+ env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
+
+ # Combine the JavaScript library files into a single C++ file and
+ # compile it.
+ js_files = [s for s in JS_FILES_FOR_TESTS]
+ js_files_src = env.JS2C(
+ ['js-files-for-cctest.cc'], js_files, **{'TYPE': 'TEST', 'COMPRESSION': 'off'})
+ js_files_obj = context.ConfigureObject(env, js_files_src, CPPPATH=['.'])
+
# There seems to be a glitch in the way scons decides where to put
# PDB files when compiling using MSVC so we specify it manually.
# This should not affect any other platforms.
+ object_files.append(js_files_obj)
return env.Program('cctest', ['cctest.cc', cctest_files, object_files],
PDB='cctest.exe.pdb')
diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp
index 0a74ce3ca..9cbcb9cfa 100644
--- a/deps/v8/test/cctest/cctest.gyp
+++ b/deps/v8/test/cctest/cctest.gyp
@@ -26,6 +26,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'variables': {
+ 'generated_file': '<(SHARED_INTERMEDIATE_DIR)/resources.cc',
+ },
'includes': [ '../../build/v8-features.gypi' ],
'targets': [
{
@@ -33,11 +36,13 @@
'type': 'executable',
'dependencies': [
'../../tools/gyp/v8.gyp:v8',
+ 'resources',
],
'include_dirs': [
'../../src',
],
'sources': [
+ '<(generated_file)',
'cctest.cc',
'gay-fixed.cc',
'gay-precision.cc',
@@ -131,5 +136,41 @@
}],
],
},
+ {
+ 'target_name': 'resources',
+ 'type': 'none',
+ 'variables': {
+ 'file_list': [
+ '../../tools/splaytree.js',
+ '../../tools/codemap.js',
+ '../../tools/csvparser.js',
+ '../../tools/consarray.js',
+ '../../tools/profile.js',
+ '../../tools/profile_view.js',
+ '../../tools/logreader.js',
+ 'log-eq-of-logging-and-traversal.js',
+ ],
+ },
+ 'actions': [
+ {
+ 'action_name': 'js2c',
+ 'inputs': [
+ '../../tools/js2c.py',
+ '<@(file_list)',
+ ],
+ 'outputs': [
+ '<(generated_file)',
+ ],
+ 'action': [
+ 'python',
+ '../../tools/js2c.py',
+ '<@(_outputs)',
+ 'TEST', # type
+ 'off', # compression
+ '<@(file_list)',
+ ],
+ }
+ ],
+ },
],
}
diff --git a/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js b/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js
index e661efe02..cd52da545 100644
--- a/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js
+++ b/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js
@@ -137,36 +137,38 @@ function RunTest() {
return entityA.size === entityB.size && entityNamesEqual(entityA, entityB);
}
- var i = 0, j = 0, k = logging_entries.length, l = traversal_entries.length;
+ var l_pos = 0, t_pos = 0;
+ var l_len = logging_entries.length, t_len = traversal_entries.length;
var comparison = [];
var equal = true;
// Do a merge-like comparison of entries. At the same address we expect to
// find the same entries. We skip builtins during log parsing, but compiled
// functions traversal may erroneously recognize them as functions, so we are
// expecting more functions in traversal vs. logging.
- while (i < k && j < l) {
- var entryA = logging_entries[i], entryB = traversal_entries[j];
+ while (l_pos < l_len && t_pos < t_len) {
+ var entryA = logging_entries[l_pos];
+ var entryB = traversal_entries[t_pos];
var cmp = addressComparator(entryA, entryB);
var entityA = entryA[1], entityB = entryB[1];
var address = entryA[0];
if (cmp < 0) {
- ++i;
+ ++l_pos;
entityB = null;
} else if (cmp > 0) {
- ++j;
+ ++t_pos;
entityA = null;
address = entryB[0];
} else {
- ++i;
- ++j;
+ ++l_pos;
+ ++t_pos;
}
var entities_equal = entitiesEqual(entityA, entityB);
if (!entities_equal) equal = false;
comparison.push([entities_equal, address, entityA, entityB]);
}
- if (i < k) equal = false;
- while (i < k) {
- var entryA = logging_entries[i++];
+ if (l_pos < l_len) equal = false;
+ while (l_pos < l_len) {
+ var entryA = logging_entries[l_pos++];
comparison.push([false, entryA[0], entryA[1], null]);
}
return [equal, comparison];
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 8d8770f13..bc9a0e2ca 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -1026,6 +1026,90 @@ THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
}
+THREADED_TEST(IsNativeError) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::Handle<Value> syntax_error = CompileRun(
+ "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
+ CHECK(syntax_error->IsNativeError());
+ v8::Handle<Value> not_error = CompileRun("{a:42}");
+ CHECK(!not_error->IsNativeError());
+ v8::Handle<Value> not_object = CompileRun("42");
+ CHECK(!not_object->IsNativeError());
+}
+
+
+THREADED_TEST(StringObject) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
+ CHECK(boxed_string->IsStringObject());
+ v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
+ CHECK(!unboxed_string->IsStringObject());
+ v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
+ CHECK(!boxed_not_string->IsStringObject());
+ v8::Handle<Value> not_object = CompileRun("0");
+ CHECK(!not_object->IsStringObject());
+ v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
+ CHECK(!as_boxed.IsEmpty());
+ Local<v8::String> the_string = as_boxed->StringValue();
+ CHECK(!the_string.IsEmpty());
+ ExpectObject("\"test\"", the_string);
+ v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
+ CHECK(new_boxed_string->IsStringObject());
+ as_boxed = new_boxed_string.As<v8::StringObject>();
+ the_string = as_boxed->StringValue();
+ CHECK(!the_string.IsEmpty());
+ ExpectObject("\"test\"", the_string);
+}
+
+
+THREADED_TEST(NumberObject) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
+ CHECK(boxed_number->IsNumberObject());
+ v8::Handle<Value> unboxed_number = CompileRun("42");
+ CHECK(!unboxed_number->IsNumberObject());
+ v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
+ CHECK(!boxed_not_number->IsNumberObject());
+ v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
+ CHECK(!as_boxed.IsEmpty());
+ double the_number = as_boxed->NumberValue();
+ CHECK_EQ(42.0, the_number);
+ v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
+ CHECK(new_boxed_number->IsNumberObject());
+ as_boxed = new_boxed_number.As<v8::NumberObject>();
+ the_number = as_boxed->NumberValue();
+ CHECK_EQ(43.0, the_number);
+}
+
+
+THREADED_TEST(BooleanObject) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
+ CHECK(boxed_boolean->IsBooleanObject());
+ v8::Handle<Value> unboxed_boolean = CompileRun("true");
+ CHECK(!unboxed_boolean->IsBooleanObject());
+ v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
+ CHECK(!boxed_not_boolean->IsBooleanObject());
+ v8::Handle<v8::BooleanObject> as_boxed =
+ boxed_boolean.As<v8::BooleanObject>();
+ CHECK(!as_boxed.IsEmpty());
+ bool the_boolean = as_boxed->BooleanValue();
+ CHECK_EQ(true, the_boolean);
+ v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
+ v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
+ CHECK(boxed_true->IsBooleanObject());
+ CHECK(boxed_false->IsBooleanObject());
+ as_boxed = boxed_true.As<v8::BooleanObject>();
+ CHECK_EQ(true, as_boxed->BooleanValue());
+ as_boxed = boxed_false.As<v8::BooleanObject>();
+ CHECK_EQ(false, as_boxed->BooleanValue());
+}
+
+
THREADED_TEST(Number) {
v8::HandleScope scope;
LocalContext env;
@@ -2048,10 +2132,15 @@ THREADED_TEST(GetSetProperty) {
THREADED_TEST(PropertyAttributes) {
v8::HandleScope scope;
LocalContext context;
+ // none
+ Local<String> prop = v8_str("none");
+ context->Global()->Set(prop, v8_num(7));
+ CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
// read-only
- Local<String> prop = v8_str("read_only");
+ prop = v8_str("read_only");
context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+ CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
Script::Compile(v8_str("read_only = 9"))->Run();
CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
context->Global()->Set(prop, v8_num(10));
@@ -2062,6 +2151,25 @@ THREADED_TEST(PropertyAttributes) {
CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
Script::Compile(v8_str("delete dont_delete"))->Run();
CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
+ CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
+ // dont-enum
+ prop = v8_str("dont_enum");
+ context->Global()->Set(prop, v8_num(28), v8::DontEnum);
+ CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
+ // absent
+ prop = v8_str("absent");
+ CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
+ Local<Value> fake_prop = v8_num(1);
+ CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
+ // exception
+ TryCatch try_catch;
+ Local<Value> exception =
+ CompileRun("({ toString: function() { throw 'exception';} })");
+ CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
+ CHECK(try_catch.HasCaught());
+ String::AsciiValue exception_value(try_catch.Exception());
+ CHECK_EQ("exception", *exception_value);
+ try_catch.Reset();
}
diff --git a/deps/v8/test/cctest/test-ast.cc b/deps/v8/test/cctest/test-ast.cc
index d1e537d9d..786a54a11 100644
--- a/deps/v8/test/cctest/test-ast.cc
+++ b/deps/v8/test/cctest/test-ast.cc
@@ -40,7 +40,7 @@ TEST(List) {
CHECK_EQ(0, list->length());
ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
- AstNode* node = new EmptyStatement();
+ AstNode* node = new(ZONE) EmptyStatement();
list->Add(node);
CHECK_EQ(1, list->length());
CHECK_EQ(node, list->at(0));
diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc
index 5704b07ac..262e7bb50 100644
--- a/deps/v8/test/cctest/test-log.cc
+++ b/deps/v8/test/cctest/test-log.cc
@@ -12,6 +12,7 @@
#include "v8.h"
#include "log.h"
#include "cpu-profiler.h"
+#include "natives.h"
#include "v8threads.h"
#include "v8utils.h"
#include "cctest.h"
@@ -469,6 +470,8 @@ TEST(IsLoggingPreserved) {
}
+typedef i::NativesCollection<i::TEST> TestSources;
+
// Test that logging of code create / move / delete events
// is equivalent to traversal of a resulting heap.
TEST(EquivalenceOfLoggingAndTraversal) {
@@ -505,38 +508,25 @@ TEST(EquivalenceOfLoggingAndTraversal) {
v8::Handle<v8::String> log_str = v8::String::New(log.start(), log.length());
initialize_logger.env()->Global()->Set(v8_str("_log"), log_str);
- const char* scripts[] = {
- "tools/splaytree.js", "tools/codemap.js", "tools/csvparser.js",
- "tools/consarray.js", "tools/profile.js", "tools/profile_view.js",
- "tools/logreader.js", "test/cctest/log-eq-of-logging-and-traversal.js"
- };
- int scripts_count = sizeof(scripts) / sizeof(scripts[0]);
- v8::Handle<v8::Value> last_result;
- for (int i = 0; i < scripts_count; ++i) {
- bool exists = true;
- i::Vector<const char> source(i::ReadFile(scripts[i], &exists, true));
- CHECK(exists);
- CHECK_GT(source.length(), 0);
- v8::Handle<v8::String> source_str =
- v8::String::New(source.start(), source.length());
- v8::TryCatch try_catch;
- v8::Handle<v8::Script> script =
- v8::Script::Compile(source_str, v8_str(scripts[i]));
- if (script.IsEmpty()) {
- v8::String::Utf8Value exception(try_catch.Exception());
- printf("compile %s: %s\n", scripts[i], *exception);
- CHECK(false);
- }
- last_result = script->Run();
- if (last_result.IsEmpty()) {
- v8::String::Utf8Value exception(try_catch.Exception());
- printf("run %s: %s\n", scripts[i], *exception);
- CHECK(false);
- }
+ i::Vector<const unsigned char> source = TestSources::GetScriptsSource();
+ v8::Handle<v8::String> source_str = v8::String::New(
+ reinterpret_cast<const char*>(source.start()), source.length());
+ v8::TryCatch try_catch;
+ v8::Handle<v8::Script> script = v8::Script::Compile(source_str, v8_str(""));
+ if (script.IsEmpty()) {
+ v8::String::Utf8Value exception(try_catch.Exception());
+ printf("compile: %s\n", *exception);
+ CHECK(false);
+ }
+ v8::Handle<v8::Value> result = script->Run();
+ if (result.IsEmpty()) {
+ v8::String::Utf8Value exception(try_catch.Exception());
+ printf("run: %s\n", *exception);
+ CHECK(false);
}
// The result either be a "true" literal or problem description.
- if (!last_result->IsTrue()) {
- v8::Local<v8::String> s = last_result->ToString();
+ if (!result->IsTrue()) {
+ v8::Local<v8::String> s = result->ToString();
i::ScopedVector<char> data(s->Length() + 1);
CHECK_NE(NULL, data.start());
s->WriteAscii(data.start());
diff --git a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js
index 584d1afda..9ed1dbbed 100644
--- a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js
+++ b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js
@@ -44,21 +44,44 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i);
if (i < exec_state.frameCount() - 1) {
- // All frames except the bottom one has normal variables a and b.
+ var expected_a = i * 2 + 1 + (i * 2 + 1) / 100;
+ var expected_b = i * 2 + 2 + (i * 2 + 2) / 100;
+ var expected_x = (i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100;
+ var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100;
+
+ // All frames except the bottom one has normal variables a and b.
assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1));
- assertEquals(i * 2 + 1 + (i * 2 + 1) / 100,
- frame.localValue(0).value());
- assertEquals(i * 2 + 2 + (i * 2 + 2) / 100,
- frame.localValue(1).value());
+ assertEquals(expected_a, frame.localValue(0).value());
+ assertEquals(expected_b, frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1));
- assertEquals((i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100,
- frame.argumentValue(0).value());
- assertEquals((i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100,
- frame.argumentValue(1).value());
+ assertEquals(expected_x, frame.argumentValue(0).value());
+ assertEquals(expected_y, frame.argumentValue(1).value());
+
+ // All frames except the bottom one have two scopes.
+ assertEquals(2, frame.scopeCount());
+ assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
+ assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
+ assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
+ assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']);
+ assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']);
+ assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']);
+
+ // Evaluate in the inlined frame.
+ assertEquals(expected_a, frame.evaluate('a').value());
+ assertEquals(expected_x, frame.evaluate('x').value());
+ assertEquals(expected_x, frame.evaluate('arguments[0]').value());
+ assertEquals(expected_a + expected_b + expected_x + expected_y,
+ frame.evaluate('a + b + x + y').value());
+ assertEquals(expected_x + expected_y,
+ frame.evaluate('arguments[0] + arguments[1]').value());
+ } else {
+ // The bottom frame only have the global scope.
+ assertEquals(1, frame.scopeCount());
+ assertEquals(debug.ScopeType.Global, frame.scope(0).scopeType());
}
// Check the frame function.
@@ -75,12 +98,13 @@ function listener(event, exec_state, event_data, data) {
// Check for construct call.
assertEquals(testingConstructCall && i == 4, frame.isConstructCall());
- // When function f is optimized (2 means YES, see runtime.cc) we
+ // When function f is optimized (1 means YES, see runtime.cc) we
// expect an optimized frame for f with g1, g2 and g3 inlined.
- if (%GetOptimizationStatus(f) == 2) {
+ if (%GetOptimizationStatus(f) == 1) {
if (i == 1 || i == 2 || i == 3) {
assertTrue(frame.isOptimizedFrame());
assertTrue(frame.isInlinedFrame());
+ assertEquals(4 - i, frame.inlinedFrameIndex());
} else if (i == 4) {
assertTrue(frame.isOptimizedFrame());
assertFalse(frame.isInlinedFrame());
diff --git a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js
index 1aaf29633..683c139d8 100644
--- a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js
+++ b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js
@@ -44,17 +44,44 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i);
if (i < exec_state.frameCount() - 1) {
+ var expected_a = i * 2 + 1;
+ var expected_b = i * 2 + 2;
+ var expected_x = (i + 1) * 2 + 1;
+ var expected_y = (i + 1) * 2 + 2;
+
// All frames except the bottom one has normal variables a and b.
assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1));
- assertEquals(i * 2 + 1, frame.localValue(0).value());
- assertEquals(i * 2 + 2, frame.localValue(1).value());
+ assertEquals(expected_a, frame.localValue(0).value());
+ assertEquals(expected_b, frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1));
- assertEquals((i + 1) * 2 + 1, frame.argumentValue(0).value());
- assertEquals((i + 1) * 2 + 2, frame.argumentValue(1).value());
+ assertEquals(expected_x, frame.argumentValue(0).value());
+ assertEquals(expected_y, frame.argumentValue(1).value());
+
+ // All frames except the bottom one have two scopes.
+ assertEquals(2, frame.scopeCount());
+ assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
+ assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
+ assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
+ assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']);
+ assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']);
+ assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']);
+
+ // Evaluate in the inlined frame.
+ assertEquals(expected_a, frame.evaluate('a').value());
+ assertEquals(expected_x, frame.evaluate('x').value());
+ assertEquals(expected_x, frame.evaluate('arguments[0]').value());
+ assertEquals(expected_a + expected_b + expected_x + expected_y,
+ frame.evaluate('a + b + x + y').value());
+ assertEquals(expected_x + expected_y,
+ frame.evaluate('arguments[0] + arguments[1]').value());
+ } else {
+ // The bottom frame only have the global scope.
+ assertEquals(1, frame.scopeCount());
+ assertEquals(debug.ScopeType.Global, frame.scope(0).scopeType());
}
// Check the frame function.
@@ -71,12 +98,13 @@ function listener(event, exec_state, event_data, data) {
// Check for construct call.
assertEquals(testingConstructCall && i == 4, frame.isConstructCall());
- // When function f is optimized (2 means YES, see runtime.cc) we
+ // When function f is optimized (1 means YES, see runtime.cc) we
// expect an optimized frame for f with g1, g2 and g3 inlined.
- if (%GetOptimizationStatus(f) == 2) {
+ if (%GetOptimizationStatus(f) == 1) {
if (i == 1 || i == 2 || i == 3) {
assertTrue(frame.isOptimizedFrame());
assertTrue(frame.isInlinedFrame());
+ assertEquals(4 - i, frame.inlinedFrameIndex());
} else if (i == 4) {
assertTrue(frame.isOptimizedFrame());
assertFalse(frame.isInlinedFrame());
diff --git a/deps/v8/test/mjsunit/debug-receiver.js b/deps/v8/test/mjsunit/debug-receiver.js
new file mode 100644
index 000000000..21cdde84a
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-receiver.js
@@ -0,0 +1,126 @@
+// 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug;
+
+var test_name;
+var listener_delegate;
+var listener_called;
+var exception;
+var expected_receiver;
+var begin_test_count = 0;
+var end_test_count = 0;
+var break_count = 0;
+
+// Debug event listener which delegates. Exceptions have to be
+// explictly caught here and checked later because exception in the
+// listener are not propagated to the surrounding JavaScript code.
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ break_count++;
+ listener_called = true;
+ listener_delegate(exec_state);
+ }
+ } catch (e) {
+ exception = e;
+ }
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+// Initialize for a new test.
+function BeginTest(name) {
+ test_name = name;
+ listener_called = false;
+ exception = null;
+ begin_test_count++;
+}
+
+
+// Check result of a test.
+function EndTest() {
+ assertTrue(listener_called, "listerner not called for " + test_name);
+ assertNull(exception, test_name);
+ end_test_count++;
+}
+
+
+// Check that the debugger correctly reflects that the receiver is not
+// converted to object for strict mode functions.
+function Strict() { "use strict"; debugger; }
+function TestStrict(receiver) {
+ expected_receiver = receiver;
+ Strict.call(receiver);
+}
+
+listener_delegate = function(exec_state) {
+ var receiver = exec_state.frame().receiver();
+ assertTrue(!receiver.isObject());
+ assertEquals(expected_receiver, receiver.value())
+}
+
+BeginTest("strict: undefined"); TestStrict(undefined); EndTest();
+BeginTest("strict: null"); TestStrict(null); EndTest();
+BeginTest("strict: 1"); TestStrict(1); EndTest();
+BeginTest("strict: 1.2"); TestStrict(1.2); EndTest();
+BeginTest("strict: 'asdf'"); TestStrict('asdf'); EndTest();
+BeginTest("strict: true"); TestStrict(true); EndTest();
+
+
+// Check that the debugger correctly reflects the object conversion of
+// the receiver for non-strict mode functions.
+function NonStrict() { debugger; }
+function TestNonStrict(receiver) {
+ // null and undefined should be transformed to the global object and
+ // primitives should be wrapped.
+ expected_receiver = (receiver == null) ? this : Object(receiver);
+ NonStrict.call(receiver);
+}
+
+listener_delegate = function(exec_state) {
+ var receiver = exec_state.frame().receiver();
+ assertTrue(receiver.isObject());
+ assertEquals(expected_receiver, receiver.value());
+}
+
+BeginTest("non-strict: undefined"); TestNonStrict(undefined); EndTest();
+BeginTest("non-strict: null"); TestNonStrict(null); EndTest();
+BeginTest("non-strict: 1"); TestNonStrict(1); EndTest();
+BeginTest("non-strict: 1.2"); TestNonStrict(1.2); EndTest();
+BeginTest("non-strict: 'asdf'"); TestNonStrict('asdf'); EndTest();
+BeginTest("non-strict: true"); TestNonStrict(true); EndTest();
+
+
+assertEquals(begin_test_count, break_count,
+ 'one or more tests did not enter the debugger');
+assertEquals(begin_test_count, end_test_count,
+ 'one or more tests did not have its result checked');
diff --git a/deps/v8/test/mjsunit/harmony/proxies.js b/deps/v8/test/mjsunit/harmony/proxies.js
index 37f351317..84641d589 100644
--- a/deps/v8/test/mjsunit/harmony/proxies.js
+++ b/deps/v8/test/mjsunit/harmony/proxies.js
@@ -28,6 +28,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// TODO(rossberg): test exception cases.
+
// Getters.
@@ -289,6 +291,50 @@ TestDefine(Proxy.create({
+// Property deletion (delete).
+
+var key
+function TestDelete(handler) {
+ var o = Proxy.create(handler)
+ assertEquals(true, delete o.a)
+ assertEquals("a", key)
+ assertEquals(true, delete o["b"])
+ assertEquals("b", key)
+
+ assertEquals(false, delete o.z1)
+ assertEquals("z1", key)
+ assertEquals(false, delete o["z2"])
+ assertEquals("z2", key);
+
+ (function() {
+ "use strict"
+ assertEquals(true, delete o.c)
+ assertEquals("c", key)
+ assertEquals(true, delete o["d"])
+ assertEquals("d", key)
+
+ assertThrows(function() { delete o.z3 }, TypeError)
+ assertEquals("z3", key)
+ assertThrows(function() { delete o["z4"] }, TypeError)
+ assertEquals("z4", key)
+ })()
+}
+
+TestDelete({
+ 'delete': function(k) { key = k; return k < "z" }
+})
+TestDelete({
+ 'delete': function(k) { return this.delete2(k) },
+ delete2: function(k) { key = k; return k < "z" }
+})
+TestDelete(Proxy.create({
+ get: function(pr, pk) {
+ return function(k) { key = k; return k < "z" }
+ }
+}))
+
+
+
// Property descriptors (Object.getOwnPropertyDescriptor).
function TestDescriptor(handler) {
@@ -358,6 +404,79 @@ assertTrue("object" == typeof Proxy.create({}))
+// Element (in).
+
+var key
+function TestIn(handler) {
+ var o = Proxy.create(handler)
+ assertTrue("a" in o)
+ assertEquals("a", key)
+ assertTrue(99 in o)
+ assertEquals("99", key)
+ assertFalse("z" in o)
+ assertEquals("z", key)
+
+ if ("b" in o) {
+ } else {
+ assertTrue(false)
+ }
+ assertEquals("b", key)
+
+ if ("zz" in o) {
+ assertTrue(false)
+ }
+ assertEquals("zz", key)
+
+ if (!("c" in o)) {
+ assertTrue(false)
+ }
+ assertEquals("c", key)
+
+ if (!("zzz" in o)) {
+ } else {
+ assertTrue(false)
+ }
+ assertEquals("zzz", key)
+}
+
+TestIn({
+ has: function(k) { key = k; return k < "z" }
+})
+TestIn({
+ has: function(k) { return this.has2(k) },
+ has2: function(k) { key = k; return k < "z" }
+})
+TestIn({
+ getPropertyDescriptor: function(k) {
+ key = k; return k < "z" ? {value: 42} : void 0
+ }
+})
+TestIn({
+ getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
+ getPropertyDescriptor2: function(k) {
+ key = k; return k < "z" ? {value: 42} : void 0
+ }
+})
+TestIn({
+ getPropertyDescriptor: function(k) {
+ key = k; return k < "z" ? {get value() { return 42 }} : void 0
+ }
+})
+TestIn({
+ get: undefined,
+ getPropertyDescriptor: function(k) {
+ key = k; return k < "z" ? {value: 42} : void 0
+ }
+})
+
+TestIn(Proxy.create({
+ get: function(pr, pk) {
+ return function(k) { key = k; return k < "z" }
+ }
+}))
+
+
+
// Instanceof (instanceof).
function TestInstanceof() {
@@ -485,3 +604,84 @@ TestKeys([], {
},
getOwnPropertyDescriptor: function(k) { return {} }
})
+
+
+
+// Fixing (Object.freeze, Object.seal, Object.preventExtensions,
+// Object.isFrozen, Object.isSealed, Object.isExtensible)
+
+function TestFix(names, handler) {
+ var proto = {p: 77}
+ var assertFixing = function(o, s, f, e) {
+ assertEquals(s, Object.isSealed(o))
+ assertEquals(f, Object.isFrozen(o))
+ assertEquals(e, Object.isExtensible(o))
+ }
+
+ var o1 = Proxy.create(handler, proto)
+ assertFixing(o1, false, false, true)
+ Object.seal(o1)
+ assertFixing(o1, true, names.length === 0, false)
+ assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o1).sort())
+ assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
+ Object.keys(o1).sort())
+ assertEquals(proto, Object.getPrototypeOf(o1))
+ assertEquals(77, o1.p)
+ for (var n in o1) {
+ var desc = Object.getOwnPropertyDescriptor(o1, n)
+ if (desc !== undefined) assertFalse(desc.configurable)
+ }
+
+ var o2 = Proxy.create(handler, proto)
+ assertFixing(o2, false, false, true)
+ Object.freeze(o2)
+ assertFixing(o2, true, true, false)
+ assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o2).sort())
+ assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
+ Object.keys(o2).sort())
+ assertEquals(proto, Object.getPrototypeOf(o2))
+ assertEquals(77, o2.p)
+ for (var n in o2) {
+ var desc = Object.getOwnPropertyDescriptor(o2, n)
+ if (desc !== undefined) assertFalse(desc.writable)
+ if (desc !== undefined) assertFalse(desc.configurable)
+ }
+
+ var o3 = Proxy.create(handler, proto)
+ assertFixing(o3, false, false, true)
+ Object.preventExtensions(o3)
+ assertFixing(o3, names.length === 0, names.length === 0, false)
+ assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o3).sort())
+ assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
+ Object.keys(o3).sort())
+ assertEquals(proto, Object.getPrototypeOf(o3))
+ assertEquals(77, o3.p)
+}
+
+TestFix([], {
+ fix: function() { return {} }
+})
+TestFix(["a", "b", "c", "d", "zz"], {
+ fix: function() {
+ return {
+ a: {value: "a", writable: true, configurable: false, enumerable: true},
+ b: {value: 33, writable: false, configurable: false, enumerable: true},
+ c: {value: 0, writable: true, configurable: true, enumerable: true},
+ d: {value: true, writable: false, configurable: true, enumerable: true},
+ zz: {value: 0, enumerable: false}
+ }
+ }
+})
+TestFix(["a"], {
+ fix: function() { return this.fix2() },
+ fix2: function() {
+ return {a: {value: 4, writable: true, configurable: true, enumerable: true}}
+ }
+})
+TestFix(["b"], {
+ get fix() {
+ return function() {
+ return {b: {configurable: true, writable: true, enumerable: true}}
+ }
+ }
+})
diff --git a/deps/v8/test/mjsunit/regress/regress-1560.js b/deps/v8/test/mjsunit/regress/regress-1560.js
new file mode 100644
index 000000000..a0aa7e64d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1560.js
@@ -0,0 +1,68 @@
+// 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.
+
+// Flags: --allow-natives-syntax --expose-gc
+
+function mkCOWArray() {
+ var a = [''];
+ assertEquals('', a[0]);
+ return a;
+}
+
+function mkArray() {
+ var a = [];
+ a[0] = '';
+ return a;
+}
+
+function mkNumberDictionary() {
+ var a = new Array();
+ a[0] = '';
+ a[100000] = '';
+ return a;
+}
+
+function write(a, i) { a[i] = "bazinga!"; }
+
+function test(factories, w) {
+ factories.forEach(function(f) { w(f(), 0); });
+ factories.forEach(function(f) { w(f(), 0); });
+ %OptimizeFunctionOnNextCall(w);
+ factories.forEach(function(f) { w(f(), 0); });
+}
+
+// Monomorphic case.
+for (var i = 0; i < 5; i++) write(mkArray(), 0);
+%OptimizeFunctionOnNextCall(write);
+write(mkCOWArray(), 0);
+var failure = mkCOWArray();
+
+// Cleanup, then polymorphic case.
+%DeoptimizeFunction(write);
+gc();
+test([mkArray, mkNumberDictionary], write);
+test([mkArray, mkNumberDictionary, mkCOWArray], write);
diff --git a/deps/v8/test/mjsunit/regress/regress-798.js b/deps/v8/test/mjsunit/regress/regress-798.js
index 423c8832a..ffee5da91 100644
--- a/deps/v8/test/mjsunit/regress/regress-798.js
+++ b/deps/v8/test/mjsunit/regress/regress-798.js
@@ -106,4 +106,3 @@ xx.c;
xx.a = 1;
xx.b = 1;
xx.c = 1;
-
diff --git a/deps/v8/test/mjsunit/unbox-double-arrays.js b/deps/v8/test/mjsunit/unbox-double-arrays.js
index 31918b376..351765eec 100644
--- a/deps/v8/test/mjsunit/unbox-double-arrays.js
+++ b/deps/v8/test/mjsunit/unbox-double-arrays.js
@@ -27,52 +27,442 @@
// Test dictionary -> double elements -> dictionary elements round trip
-var foo = new Array(500000);
+// Flags: --allow-natives-syntax --unbox-double-arrays --expose-gc
+var large_array_size = 100000;
+var approx_dict_to_elements_threshold = 75000;
-function func(a) {
- for (var i= 0; i < 100000; ++i ) {
- a[i] = i+0.5;
+var name = 0;
+
+function expected_array_value(i) {
+ if ((i % 2) == 0) {
+ return i;
+ } else {
+ return i + 0.5;
+ }
+}
+
+function force_to_fast_double_array(a) {
+ a[large_array_size - 2] = 1;
+ for (var i= 0; i < approx_dict_to_elements_threshold; ++i ) {
+ a[i] = expected_array_value(i);
}
+ assertTrue(%HasFastDoubleElements(a));
}
-func(foo);
+function make_object_like_array(size) {
+ obj = new Object();
+ obj.length = size;
+ return obj;
+}
+
+function testOneArrayType(allocator) {
+ var large_array = new allocator(large_array_size);
+ force_to_fast_double_array(large_array);
+ var six = 6;
+
+ for (var i= 0; i < approx_dict_to_elements_threshold; i += 501 ) {
+ assertEquals(expected_array_value(i), large_array[i]);
+ }
+
+ // This function has a constant and won't get inlined.
+ function computed_6() {
+ return six;
+ }
+
+ // Multiple versions of the test function makes sure that IC/Crankshaft state
+ // doesn't get reused.
+ function test_various_loads(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ assertEquals(value_5, a[5]);
+ assertEquals(value_6, a[6]);
+ assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ assertEquals(value_7, a[7]);
+ assertEquals(undefined, a[large_array_size-1]);
+ assertEquals(undefined, a[-1]);
+ assertEquals(large_array_size, a.length);
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ function test_various_loads2(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ assertEquals(value_5, a[5]);
+ assertEquals(value_6, a[6]);
+ assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ assertEquals(value_7, a[7]);
+ assertEquals(undefined, a[large_array_size-1]);
+ assertEquals(undefined, a[-1]);
+ assertEquals(large_array_size, a.length);
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ function test_various_loads3(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ assertEquals(value_5, a[5]);
+ assertEquals(value_6, a[6]);
+ assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ assertEquals(value_7, a[7]);
+ assertEquals(undefined, a[large_array_size-1]);
+ assertEquals(undefined, a[-1]);
+ assertEquals(large_array_size, a.length);
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ function test_various_loads4(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ assertEquals(value_5, a[5]);
+ assertEquals(value_6, a[6]);
+ assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ assertEquals(value_7, a[7]);
+ assertEquals(undefined, a[large_array_size-1]);
+ assertEquals(undefined, a[-1]);
+ assertEquals(large_array_size, a.length);
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ function test_various_loads5(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ assertEquals(value_5, a[5]);
+ assertEquals(value_6, a[6]);
+ assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ assertEquals(value_7, a[7]);
+ assertEquals(undefined, a[large_array_size-1]);
+ assertEquals(undefined, a[-1]);
+ assertEquals(large_array_size, a.length);
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ function test_various_loads6(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ assertEquals(value_5, a[5]);
+ assertEquals(value_6, a[6]);
+ assertEquals(value_6, a[computed_6()]); // Test non-constant key
+ assertEquals(value_7, a[7]);
+ assertEquals(undefined, a[large_array_size-1]);
+ assertEquals(undefined, a[-1]);
+ assertEquals(large_array_size, a.length);
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ function test_various_stores(a, value_5, value_6, value_7) {
+ assertTrue(%HasFastDoubleElements(a));
+ a[5] = value_5;
+ a[computed_6()] = value_6;
+ a[7] = value_7;
+ assertTrue(%HasFastDoubleElements(a));
+ }
+
+ // Test double and integer values
+ test_various_loads(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ test_various_loads(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ test_various_loads(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ %OptimizeFunctionOnNextCall(test_various_loads);
+ test_various_loads(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+
+ // Test NaN values
+ test_various_stores(large_array, NaN, -NaN, expected_array_value(7));
+
+ test_various_loads2(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+ test_various_loads2(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+ test_various_loads2(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+ %OptimizeFunctionOnNextCall(test_various_loads2);
+ test_various_loads2(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+
+ // Test Infinity values
+ test_various_stores(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+
+ test_various_loads3(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+ test_various_loads3(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+ test_various_loads3(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+ %OptimizeFunctionOnNextCall(test_various_loads3);
+ test_various_loads3(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+
+ // Test the hole for the default runtime implementation.
+ delete large_array[5];
+ delete large_array[6];
+ test_various_loads4(large_array,
+ undefined,
+ undefined,
+ expected_array_value(7));
+
+ // Test the keyed load IC implementation when the value is the hole.
+ test_various_stores(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ test_various_loads5(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ test_various_loads5(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ delete large_array[5];
+ delete large_array[6];
+ test_various_loads5(large_array,
+ undefined,
+ undefined,
+ expected_array_value(7));
+ test_various_loads5(large_array,
+ undefined,
+ undefined,
+ expected_array_value(7));
-for (var i= 0; i < 100000; i += 500 ) {
- assertEquals(i+0.5, foo[i]);
+ // Make sure Crankshaft code handles the hole correctly (bailout)
+ test_various_stores(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ test_various_loads6(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ test_various_loads6(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+ %OptimizeFunctionOnNextCall(test_various_loads6);
+ test_various_loads6(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+
+ delete large_array[5];
+ delete large_array[6];
+ test_various_loads6(large_array,
+ undefined,
+ undefined,
+ expected_array_value(7));
+
+ // Test stores for non-NaN.
+ %OptimizeFunctionOnNextCall(test_various_stores);
+ test_various_stores(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+
+ test_various_stores(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+
+ test_various_loads6(large_array,
+ expected_array_value(5),
+ expected_array_value(6),
+ expected_array_value(7));
+
+ // Test NaN behavior for stores.
+ test_various_stores(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+
+ test_various_stores(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+
+ test_various_loads6(large_array,
+ NaN,
+ -NaN,
+ expected_array_value(7));
+
+ // Test Infinity behavior for stores.
+ test_various_stores(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+
+ test_various_stores(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+
+ test_various_loads6(large_array,
+ Infinity,
+ -Infinity,
+ expected_array_value(7));
+
+ assertTrue(%GetOptimizationStatus(test_various_stores) != 2);
+
+ // Make sure that we haven't converted from fast double.
+ assertTrue(%HasFastDoubleElements(large_array));
}
-delete foo[5];
-// Don't use assertEquals for comparison to undefined due to
-assertTrue(undefined === foo[5]);
-assertTrue(undefined === foo[500000-1]);
-assertTrue(undefined === foo[-1]);
-assertEquals(500000, foo.length);
+testOneArrayType(make_object_like_array);
+testOneArrayType(Array);
+
+var large_array = new Array(large_array_size);
+force_to_fast_double_array(large_array);
+assertTrue(%HasFastDoubleElements(large_array));
// Cause the array to grow beyond it's JSArray length. This will double the
// size of the capacity and force the array into "slow" dictionary case.
-foo[500001] = 50;
-assertEquals(50, foo[500001]);
-assertEquals(500002, foo.length);
-assertTrue(undefined === foo[5])
-assertTrue(undefined === foo[500000-1])
-assertTrue(undefined === foo[-1])
-assertEquals(500002, foo.length);
+large_array[5] = Infinity;
+large_array[large_array_size+10001] = 50;
+assertTrue(%HasDictionaryElements(large_array));
+assertEquals(50, large_array[large_array_size+10001]);
+assertEquals(large_array_size+10002, large_array.length);
+assertEquals(Infinity, large_array[5]);
+assertEquals(undefined, large_array[large_array_size-1]);
+assertEquals(undefined, large_array[-1]);
+assertEquals(large_array_size+10002, large_array.length);
// Test dictionary -> double elements -> fast elements.
-
-var foo2 = new Array(500000);
-func(foo2);
-delete foo2[5];
+var large_array2 = new Array(large_array_size);
+force_to_fast_double_array(large_array2);
+delete large_array2[5];
// Convert back to fast elements and make sure the contents of the array are
// unchanged.
-foo2[25] = new Object();
-for (var i= 0; i < 100000; i += 500 ) {
+large_array2[25] = new Object();
+assertTrue(%HasFastElements(large_array2));
+for (var i= 0; i < approx_dict_to_elements_threshold; i += 500 ) {
if (i != 25 && i != 5) {
- assertEquals(i+0.5, foo2[i]);
+ assertEquals(expected_array_value(i), large_array2[i]);
}
}
-assertTrue(undefined === foo2[5])
-assertTrue(undefined === foo2[500000-1])
-assertTrue(undefined === foo2[-1])
-assertEquals(500000, foo2.length);
+assertEquals(undefined, large_array2[5]);
+assertEquals(undefined, large_array2[large_array_size-1]);
+assertEquals(undefined, large_array2[-1]);
+assertEquals(large_array_size, large_array2.length);
+
+// Make sure it's possible to change the array's length and that array is still
+// intact after the resize.
+var large_array3 = new Array(large_array_size);
+force_to_fast_double_array(large_array3);
+large_array3.length = 60000;
+assertEquals(60000, large_array3.length);
+assertEquals(undefined, large_array3[60000]);
+assertTrue(%HasFastDoubleElements(large_array3));
+assertEquals(expected_array_value(5), large_array3[5]);
+assertEquals(expected_array_value(6), large_array3[6]);
+assertEquals(expected_array_value(7), large_array3[7]);
+assertEquals(expected_array_value(large_array3.length-1),
+ large_array3[large_array3.length-1]);
+assertEquals(undefined, large_array3[large_array_size-1]);
+assertEquals(undefined, large_array3[-1]);
+gc();
+
+for (var i= 0; i < large_array3.length; i += 501 ) {
+ assertEquals(expected_array_value(i), large_array3[i]);
+}
+
+large_array3.length = 25;
+assertEquals(25, large_array3.length);
+assertTrue(%HasFastDoubleElements(large_array3));
+assertEquals(undefined, large_array3[25]);
+assertEquals(expected_array_value(5), large_array3[5]);
+assertEquals(expected_array_value(6), large_array3[6]);
+assertEquals(expected_array_value(7), large_array3[7]);
+assertEquals(expected_array_value(large_array3.length-1),
+ large_array3[large_array3.length-1]);
+assertEquals(undefined, large_array3[large_array_size-1]);
+assertEquals(undefined, large_array3[-1]);
+gc();
+
+for (var i= 0; i < large_array3.length; ++i) {
+ assertEquals(expected_array_value(i), large_array3[i]);
+}
+
+large_array3.length = 100;
+assertEquals(100, large_array3.length);
+large_array3[95] = 95;
+assertTrue(%HasFastDoubleElements(large_array3));
+assertEquals(undefined, large_array3[100]);
+assertEquals(95, large_array3[95]);
+assertEquals(expected_array_value(5), large_array3[5]);
+assertEquals(expected_array_value(6), large_array3[6]);
+assertEquals(expected_array_value(7), large_array3[7]);
+assertEquals(undefined, large_array3[large_array3.length-1]);
+assertEquals(undefined, large_array3[large_array_size-1]);
+assertEquals(undefined, large_array3[-1]);
+gc();
+
+// Test apply on arrays backed by double elements.
+function called_by_apply(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
+ assertEquals(expected_array_value(0), arg0);
+ assertEquals(NaN, arg1);
+ assertEquals(-NaN, arg2);
+ assertEquals(Infinity, arg3);
+ assertEquals(-Infinity, arg4);
+ assertEquals(expected_array_value(5), arg5);
+}
+
+large_array3[1] = NaN;
+large_array3[2] = -NaN;
+large_array3[3] = Infinity;
+large_array3[4] = -Infinity;
+
+function call_apply() {
+ assertTrue(%HasFastDoubleElements(large_array3));
+ called_by_apply.apply({}, large_array3);
+}
+
+call_apply();
+call_apply();
+call_apply();
+%OptimizeFunctionOnNextCall(call_apply);
+call_apply();
+call_apply();
+call_apply();
+
+function test_for_in() {
+ // Due to previous tests, keys 0..25 and 95 should be present.
+ next_expected = 0;
+ assertTrue(%HasFastDoubleElements(large_array3));
+ for (x in large_array3) {
+ assertTrue(next_expected++ == x);
+ if (next_expected == 25) {
+ next_expected = 95;
+ }
+ }
+ assertTrue(next_expected == 96);
+}
+
+test_for_in();
+test_for_in();
+test_for_in();
+%OptimizeFunctionOnNextCall(test_for_in);
+test_for_in();
+test_for_in();
+test_for_in();
diff --git a/deps/v8/test/test262/test262.status b/deps/v8/test/test262/test262.status
index f68b85db7..8cee21076 100644
--- a/deps/v8/test/test262/test262.status
+++ b/deps/v8/test/test262/test262.status
@@ -1138,33 +1138,6 @@ prefix ietestcenter
15.4.4.20-1-5: FAIL
# Bug? Array.prototype.filter applied to string primitive
15.4.4.20-1-7: FAIL
-# Bug? Array.prototype.filter - value of 'length' is a number (value is
-# negative)
-15.4.4.20-3-7: FAIL
-# Bug? Array.prototype.filter - value of 'length' is a number (value is
-# Infinity)
-# V8 timeout
-15.4.4.20-3-8: SKIP
-# Bug? Array.prototype.filter - 'length' is a string containing a negative
-# number
-15.4.4.20-3-12: FAIL
-# Bug? Array.prototype.filter - 'length' is a string containing a decimal number
-15.4.4.20-3-13: FAIL
-# Bug? Array.prototype.filter - 'length' is a string containing +/-Infinity
-15.4.4.20-3-14: SKIP
-# Bug? Array.prototype.filter - value of 'length' is a positive non-integer,
-# ensure truncation occurs in the proper direction
-# V8 timeout
-15.4.4.20-3-24: FAIL
-# Bug? Array.prototype.filter - value of 'length' is a negative non-integer,
-# ensure truncation occurs in the proper direction
-15.4.4.20-3-25: FAIL
-# Bug? Array.prototype.filter - value of 'length' is boundary value (2^32)
-# V8 timeout
-15.4.4.20-3-28: SKIP
-# Bug? Array.prototype.filter - value of 'length' is boundary value (2^32 + 1)
-# V8 timeout
-15.4.4.20-3-29: SKIP
# Bug? Array.prototype.filter - side effects produced by step 2 are visible when
# an exception occurs
15.4.4.20-4-8: FAIL
@@ -1220,33 +1193,6 @@ prefix ietestcenter
15.4.4.21-1-5: FAIL
# Bug? Array.prototype.reduce applied to string primitive
15.4.4.21-1-7: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is a number (value is
-# negative)
-15.4.4.21-3-7: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is a number (value is
-# Infinity)
-# V8 timeout.
-15.4.4.21-3-8: SKIP
-# Bug? Array.prototype.reduce - 'length' is a string containing a negative
-# number
-15.4.4.21-3-12: FAIL
-# Bug? Array.prototype.reduce - 'length' is a string containing a decimal number
-15.4.4.21-3-13: FAIL
-# Bug? Array.prototype.reduce - 'length' is a string containing +/-Infinity
-# V8 timeout.
-15.4.4.21-3-14: SKIP
-# Bug? Array.prototype.reduce - value of 'length' is a positive non-integer,
-# ensure truncation occurs in the proper direction
-15.4.4.21-3-24: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is a negative non-integer,
-# ensure truncation occurs in the proper direction
-15.4.4.21-3-25: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is boundary value (2^32)
-# V8 timeout.
-15.4.4.21-3-28: SKIP
-# Bug? Array.prototype.reduce - value of 'length' is boundary value (2^32 + 1)
-# V8 timeout.
-15.4.4.21-3-29: SKIP
# Bug? Array.prototype.reduce - side effects produced by step 2 are visible when
# an exception occurs
15.4.4.21-4-8: FAIL
@@ -1274,36 +1220,6 @@ prefix ietestcenter
15.4.4.22-1-5: FAIL
# Bug? Array.prototype.reduceRight applied to string primitive
15.4.4.22-1-7: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a number (value is
-# negative)
-15.4.4.22-3-7: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a number (value is
-# Infinity)
-# V8 timeout.
-15.4.4.22-3-8: SKIP
-# Bug? Array.prototype.reduceRight - value of 'length' is a string containing a
-# negative number
-15.4.4.22-3-12: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a string containing a
-# decimal number
-15.4.4.22-3-13: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a string containing
-# +/-Infinity
-# V8 timeout.
-15.4.4.22-3-14: SKIP
-# Bug? Array.prototype.reduceRight - value of 'length' is a positive
-# non-integer, ensure truncation occurs in the proper direction
-15.4.4.22-3-24: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a negative
-# non-integer, ensure truncation occurs in the proper direction
-15.4.4.22-3-25: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is boundary value (2^32)
-# V8 timeout.
-15.4.4.22-3-28: SKIP
-# Bug? Array.prototype.reduceRight - value of 'length' is boundary value (2^32 +
-# 1)
-# V8 timeout.
-15.4.4.22-3-29: SKIP
# Bug? Array.prototype.reduceRight - side effects produced by step 2 are visible
# when an exception occurs
15.4.4.22-4-8: FAIL
diff --git a/deps/v8/tools/grokdump.py b/deps/v8/tools/grokdump.py
index 74521ad21..468e7cc6b 100755
--- a/deps/v8/tools/grokdump.py
+++ b/deps/v8/tools/grokdump.py
@@ -291,6 +291,7 @@ class MinidumpReader(object):
self.exception = None
self.exception_context = None
self.memory_list = None
+ self.memory_list64 = None
self.thread_map = {}
for d in directories:
DebugPrint(d)
@@ -311,16 +312,17 @@ class MinidumpReader(object):
self.thread_map[thread.id] = thread
elif d.stream_type == MD_MEMORY_LIST_STREAM:
print >>sys.stderr, "Warning: not a full minidump"
- ml = MINIDUMP_MEMORY_LIST.Read(self.minidump, d.location.rva)
- DebugPrint(ml)
- for m in ml.ranges:
- DebugPrint(m)
- elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
assert self.memory_list is None
- self.memory_list = MINIDUMP_MEMORY_LIST64.Read(
+ self.memory_list = MINIDUMP_MEMORY_LIST.Read(
self.minidump, d.location.rva)
assert ctypes.sizeof(self.memory_list) == d.location.data_size
DebugPrint(self.memory_list)
+ elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
+ assert self.memory_list64 is None
+ self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read(
+ self.minidump, d.location.rva)
+ assert ctypes.sizeof(self.memory_list64) == d.location.data_size
+ DebugPrint(self.memory_list64)
def IsValidAddress(self, address):
return self.FindLocation(address) is not None
@@ -338,12 +340,16 @@ class MinidumpReader(object):
return self.minidump[location:location + size]
def FindLocation(self, address):
- # TODO(vitalyr): only works for full minidumps (...64 structure variants).
offset = 0
- for r in self.memory_list.ranges:
- if r.start <= address < r.start + r.size:
- return self.memory_list.base_rva + offset + address - r.start
+ if self.memory_list64 is not None:
+ for r in self.memory_list64.ranges:
+ if r.start <= address < r.start + r.size:
+ return self.memory_list64.base_rva + offset + address - r.start
offset += r.size
+ if self.memory_list is not None:
+ for r in self.memory_list.ranges:
+ if r.start <= address < r.start + r.memory.data_size:
+ return r.memory.rva + address - r.start
return None
def GetDisasmLines(self, address, size):