summaryrefslogtreecommitdiff
path: root/deps/v8
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-04-08 20:25:29 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2013-04-08 20:35:27 +0200
commit587e83c6d6fa9bba14f5b629fa2ee905dc6881e8 (patch)
tree49ef341f730dbecbd8a8ea354be0ac35317a30fb /deps/v8
parent1fd95b57bf51b548651ef7868ce2dd8e65e7cf6f (diff)
downloadnode-587e83c6d6fa9bba14f5b629fa2ee905dc6881e8.tar.gz
v8: upgrade to 3.17.16
Diffstat (limited to 'deps/v8')
-rw-r--r--deps/v8/.gitignore5
-rw-r--r--deps/v8/ChangeLog40
-rw-r--r--deps/v8/OWNERS2
-rw-r--r--deps/v8/build/common.gypi9
-rw-r--r--deps/v8/include/v8-profiler.h119
-rw-r--r--deps/v8/include/v8.h16
-rw-r--r--deps/v8/src/api.cc181
-rw-r--r--deps/v8/src/api.h7
-rw-r--r--deps/v8/src/apiutils.h4
-rw-r--r--deps/v8/src/arm/builtins-arm.cc21
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc110
-rw-r--r--deps/v8/src/arm/codegen-arm.cc6
-rw-r--r--deps/v8/src/arm/full-codegen-arm.cc30
-rw-r--r--deps/v8/src/arm/lithium-arm.cc43
-rw-r--r--deps/v8/src/arm/lithium-arm.h16
-rw-r--r--deps/v8/src/arm/lithium-codegen-arm.cc82
-rw-r--r--deps/v8/src/arm/lithium-codegen-arm.h4
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc82
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h16
-rw-r--r--deps/v8/src/arm/simulator-arm.cc26
-rw-r--r--deps/v8/src/arm/simulator-arm.h6
-rw-r--r--deps/v8/src/arm/stub-cache-arm.cc45
-rw-r--r--deps/v8/src/array.js210
-rw-r--r--deps/v8/src/assembler.cc11
-rw-r--r--deps/v8/src/ast.cc12
-rw-r--r--deps/v8/src/ast.h83
-rw-r--r--deps/v8/src/bootstrapper.cc36
-rw-r--r--deps/v8/src/code-stubs-hydrogen.cc138
-rw-r--r--deps/v8/src/code-stubs.cc11
-rw-r--r--deps/v8/src/code-stubs.h69
-rw-r--r--deps/v8/src/compiler.cc1
-rw-r--r--deps/v8/src/contexts.h4
-rw-r--r--deps/v8/src/d8.cc8
-rw-r--r--deps/v8/src/d8.h5
-rw-r--r--deps/v8/src/d8.js3
-rw-r--r--deps/v8/src/debug.cc9
-rw-r--r--deps/v8/src/debug.h1
-rw-r--r--deps/v8/src/deoptimizer.cc106
-rw-r--r--deps/v8/src/deoptimizer.h12
-rw-r--r--deps/v8/src/elements-kind.h9
-rw-r--r--deps/v8/src/flag-definitions.h9
-rw-r--r--deps/v8/src/frames.cc23
-rw-r--r--deps/v8/src/full-codegen.cc28
-rw-r--r--deps/v8/src/gdb-jit.cc39
-rw-r--r--deps/v8/src/gdb-jit.h4
-rw-r--r--deps/v8/src/global-handles.cc7
-rw-r--r--deps/v8/src/handles-inl.h2
-rw-r--r--deps/v8/src/handles.cc29
-rw-r--r--deps/v8/src/handles.h10
-rw-r--r--deps/v8/src/heap-inl.h4
-rw-r--r--deps/v8/src/heap-profiler.cc125
-rw-r--r--deps/v8/src/heap-profiler.h46
-rw-r--r--deps/v8/src/heap-snapshot-generator-inl.h1
-rw-r--r--deps/v8/src/heap-snapshot-generator.cc12
-rw-r--r--deps/v8/src/heap-snapshot-generator.h11
-rw-r--r--deps/v8/src/heap.cc28
-rw-r--r--deps/v8/src/heap.h9
-rw-r--r--deps/v8/src/hydrogen-instructions.cc35
-rw-r--r--deps/v8/src/hydrogen-instructions.h77
-rw-r--r--deps/v8/src/hydrogen.cc601
-rw-r--r--deps/v8/src/hydrogen.h80
-rw-r--r--deps/v8/src/ia32/builtins-ia32.cc43
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.cc108
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc9
-rw-r--r--deps/v8/src/ia32/full-codegen-ia32.cc31
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.cc28
-rw-r--r--deps/v8/src/ia32/lithium-ia32.cc41
-rw-r--r--deps/v8/src/ia32/lithium-ia32.h14
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc88
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.h32
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc44
-rw-r--r--deps/v8/src/ic-inl.h7
-rw-r--r--deps/v8/src/ic.cc271
-rw-r--r--deps/v8/src/ic.h7
-rw-r--r--deps/v8/src/interpreter-irregexp.cc10
-rw-r--r--deps/v8/src/isolate.cc25
-rw-r--r--deps/v8/src/isolate.h3
-rw-r--r--deps/v8/src/json-parser.h55
-rw-r--r--deps/v8/src/json-stringifier.h92
-rw-r--r--deps/v8/src/log.cc91
-rw-r--r--deps/v8/src/log.h1
-rw-r--r--deps/v8/src/macros.py5
-rw-r--r--deps/v8/src/messages.js104
-rw-r--r--deps/v8/src/mips/OWNERS1
-rw-r--r--deps/v8/src/mips/assembler-mips.cc10
-rw-r--r--deps/v8/src/mips/assembler-mips.h1
-rw-r--r--deps/v8/src/mips/builtins-mips.cc21
-rw-r--r--deps/v8/src/mips/code-stubs-mips.cc141
-rw-r--r--deps/v8/src/mips/codegen-mips.cc7
-rw-r--r--deps/v8/src/mips/full-codegen-mips.cc30
-rw-r--r--deps/v8/src/mips/lithium-codegen-mips.cc90
-rw-r--r--deps/v8/src/mips/lithium-codegen-mips.h4
-rw-r--r--deps/v8/src/mips/lithium-mips.cc43
-rw-r--r--deps/v8/src/mips/lithium-mips.h17
-rw-r--r--deps/v8/src/mips/macro-assembler-mips.cc322
-rw-r--r--deps/v8/src/mips/macro-assembler-mips.h13
-rw-r--r--deps/v8/src/mips/regexp-macro-assembler-mips.cc1
-rw-r--r--deps/v8/src/mips/simulator-mips.cc28
-rw-r--r--deps/v8/src/mips/simulator-mips.h6
-rw-r--r--deps/v8/src/mips/stub-cache-mips.cc45
-rw-r--r--deps/v8/src/mirror-debugger.js2
-rw-r--r--deps/v8/src/object-observe.js3
-rw-r--r--deps/v8/src/objects-debug.cc12
-rw-r--r--deps/v8/src/objects-inl.h55
-rw-r--r--deps/v8/src/objects-printer.cc15
-rw-r--r--deps/v8/src/objects-visiting-inl.h19
-rw-r--r--deps/v8/src/objects-visiting.cc5
-rw-r--r--deps/v8/src/objects-visiting.h1
-rw-r--r--deps/v8/src/objects.cc303
-rw-r--r--deps/v8/src/objects.h69
-rw-r--r--deps/v8/src/parser.cc95
-rw-r--r--deps/v8/src/parser.h10
-rw-r--r--deps/v8/src/platform-linux.cc4
-rw-r--r--deps/v8/src/platform-posix.cc17
-rw-r--r--deps/v8/src/platform.h2
-rw-r--r--deps/v8/src/preparser.cc60
-rw-r--r--deps/v8/src/preparser.h38
-rw-r--r--deps/v8/src/prettyprinter.cc11
-rw-r--r--deps/v8/src/property.h8
-rw-r--r--deps/v8/src/runtime.cc993
-rw-r--r--deps/v8/src/runtime.h14
-rw-r--r--deps/v8/src/runtime.js12
-rwxr-xr-xdeps/v8/src/scanner.cc2
-rw-r--r--deps/v8/src/scanner.h3
-rw-r--r--deps/v8/src/spaces-inl.h17
-rw-r--r--deps/v8/src/spaces.cc8
-rw-r--r--deps/v8/src/spaces.h5
-rw-r--r--deps/v8/src/stub-cache.cc82
-rw-r--r--deps/v8/src/stub-cache.h12
-rw-r--r--deps/v8/src/symbol.js56
-rw-r--r--deps/v8/src/token.h1
-rw-r--r--deps/v8/src/type-info.cc17
-rw-r--r--deps/v8/src/typedarray.js98
-rw-r--r--deps/v8/src/v8globals.h2
-rw-r--r--deps/v8/src/v8natives.js29
-rw-r--r--deps/v8/src/v8utils.h33
-rw-r--r--deps/v8/src/version.cc2
-rw-r--r--deps/v8/src/x64/builtins-x64.cc48
-rw-r--r--deps/v8/src/x64/code-stubs-x64.cc67
-rw-r--r--deps/v8/src/x64/codegen-x64.cc6
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc30
-rw-r--r--deps/v8/src/x64/lithium-codegen-x64.cc22
-rw-r--r--deps/v8/src/x64/lithium-x64.cc35
-rw-r--r--deps/v8/src/x64/lithium-x64.h16
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc74
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.h28
-rw-r--r--deps/v8/src/x64/stub-cache-x64.cc43
-rw-r--r--deps/v8/test/cctest/test-api.cc22
-rw-r--r--deps/v8/test/cctest/test-cpu-profiler.cc104
-rw-r--r--deps/v8/test/cctest/test-heap-profiler.cc230
-rw-r--r--deps/v8/test/cctest/test-heap.cc4
-rw-r--r--deps/v8/test/cctest/test-profile-generator.cc10
-rw-r--r--deps/v8/test/cctest/test-strings.cc4
-rw-r--r--deps/v8/test/message/overwritten-builtins.out1
-rw-r--r--deps/v8/test/mjsunit/array-non-smi-length.js46
-rw-r--r--deps/v8/test/mjsunit/array-shift.js14
-rw-r--r--deps/v8/test/mjsunit/array-splice.js10
-rw-r--r--deps/v8/test/mjsunit/array-unshift.js17
-rw-r--r--deps/v8/test/mjsunit/compiler/rotate.js1
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate-locals.js16
-rw-r--r--deps/v8/test/mjsunit/debug-liveedit-compile-error.js2
-rw-r--r--deps/v8/test/mjsunit/elements-kind.js7
-rw-r--r--deps/v8/test/mjsunit/error-accessors.js1
-rw-r--r--deps/v8/test/mjsunit/harmony/generators-parsing.js100
-rw-r--r--deps/v8/test/mjsunit/harmony/object-observe.js25
-rw-r--r--deps/v8/test/mjsunit/harmony/proxies-symbols.js106
-rw-r--r--deps/v8/test/mjsunit/harmony/symbols.js164
-rw-r--r--deps/v8/test/mjsunit/harmony/typedarrays.js136
-rw-r--r--deps/v8/test/mjsunit/json.js117
-rw-r--r--deps/v8/test/mjsunit/json2.js65
-rw-r--r--deps/v8/test/mjsunit/nans.js103
-rw-r--r--deps/v8/test/mjsunit/regress/external-and-normal-array-polymorphism.js48
-rw-r--r--deps/v8/test/mjsunit/regress/negative_lookup.js65
-rw-r--r--deps/v8/test/mjsunit/regress/readonly1.js71
-rw-r--r--deps/v8/test/mjsunit/regress/readonly2.js62
-rw-r--r--deps/v8/test/mjsunit/regress/readonly3.js65
-rw-r--r--deps/v8/test/mjsunit/regress/readonly4.js74
-rw-r--r--deps/v8/test/mjsunit/regress/regress-105.js44
-rw-r--r--deps/v8/test/mjsunit/regress/regress-166379.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-201590.js66
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2374.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2419.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2438.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2444.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2451.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2564.js122
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2570.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2593.js61
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2596.js56
-rw-r--r--deps/v8/test/mjsunit/regress/regress-753.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-146910.js15
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-158185.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-171715.js87
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-178790.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-217858.js40
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-222893.js64
-rw-r--r--deps/v8/test/mjsunit/regress/regress-json-stringify-gc.js1
-rw-r--r--deps/v8/test/mjsunit/regress/regress-latin-1.js1
-rw-r--r--deps/v8/test/mjsunit/regress/setter.js66
-rw-r--r--deps/v8/test/mjsunit/shift-for-integer-div.js1
-rw-r--r--deps/v8/test/mjsunit/string-natives.js1
-rwxr-xr-xdeps/v8/tools/grokdump.py287
-rw-r--r--deps/v8/tools/gyp/v8.gyp3
203 files changed, 6256 insertions, 3512 deletions
diff --git a/deps/v8/.gitignore b/deps/v8/.gitignore
index 0bf931335..fe8425f02 100644
--- a/deps/v8/.gitignore
+++ b/deps/v8/.gitignore
@@ -18,6 +18,7 @@
#*#
*~
.cpplint-cache
+.d8_history
d8
d8_g
shell
@@ -50,3 +51,7 @@ shell_g
/xcodebuild
TAGS
*.Makefile
+GTAGS
+GRTAGS
+GSYMS
+GPATH
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 11c80d717..5bd017fc0 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,43 @@
+2013-04-04: Version 3.17.16
+
+ Stack trace API: poison stack frames below the first strict mode frame.
+ (issue 2564)
+
+ Made Isolate::GetHeapStatistics robust against half-initialized
+ isolates (Chromium issue 2591).
+
+ Finished implementation of ES6 symbols aka. private names (issue 2158).
+
+ Performance and stability improvements on all platforms.
+
+
+2013-03-21: Version 3.17.15
+
+ Rolled back API changes to maintain compatibility with older
+ 3.17.x versions of V8.
+
+ Disable zapping of global handles in release mode.
+
+ Always mark the entire valid prefix of the descriptor array.
+ (Chromium issue 196331)
+
+ Use internal memcpy for CopyWords and when copying code.
+ (Chromium issue 196330)
+
+ Performance and stability improvements on all platforms.
+
+
+2013-03-20: Version 3.17.14
+
+ Use internal memcpy when initializing code objects.
+ (Chromium issue 196330)
+
+ Disabled weak embedded maps because of crashes.
+ (Chromium issues 172489, 217858)
+
+ Performance and stability improvements on all platforms.
+
+
2013-03-19: Version 3.17.13
Turned Flags into a uint32_t typedef (Chromium issue 194749).
diff --git a/deps/v8/OWNERS b/deps/v8/OWNERS
index 941e5fe07..0333d1518 100644
--- a/deps/v8/OWNERS
+++ b/deps/v8/OWNERS
@@ -1,4 +1,6 @@
danno@chromium.org
+dslomov@chromium.org
+hpayer@chromium.org
jkummerow@chromium.org
mmassi@chromium.org
mstarzinger@chromium.org
diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi
index 38ed4f4c9..a3c9ed094 100644
--- a/deps/v8/build/common.gypi
+++ b/deps/v8/build/common.gypi
@@ -409,6 +409,15 @@
}],
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
or OS=="android"', {
+ 'cflags!': [
+ '-O2',
+ '-Os',
+ ],
+ 'cflags': [
+ '-fdata-sections',
+ '-ffunction-sections',
+ '-O3',
+ ],
'conditions': [
[ 'gcc_version==44 and clang==0', {
'cflags': [
diff --git a/deps/v8/include/v8-profiler.h b/deps/v8/include/v8-profiler.h
index 41fe8a199..68f377c60 100644
--- a/deps/v8/include/v8-profiler.h
+++ b/deps/v8/include/v8-profiler.h
@@ -135,7 +135,7 @@ class V8EXPORT CpuProfile {
/**
* Returns number of samples recorded. The samples are not recorded unless
- * |record_samples| parameter of CpuProfiler::StartProfiling is true.
+ * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
*/
int GetSamplesCount() const;
@@ -158,7 +158,8 @@ class V8EXPORT CpuProfile {
/**
- * Interface for controlling CPU profiling.
+ * Interface for controlling CPU profiling. Instance of the
+ * profiler can be retrieved using v8::Isolate::GetCpuProfiler.
*/
class V8EXPORT CpuProfiler {
public:
@@ -171,22 +172,34 @@ class V8EXPORT CpuProfiler {
* obtaining profiling results.
*/
+ /** Deprecated. Use GetProfileCount instead. */
+ static int GetProfilesCount();
/**
* Returns the number of profiles collected (doesn't include
* profiles that are being collected at the moment of call.)
*/
- static int GetProfilesCount();
+ int GetProfileCount();
- /** Returns a profile by index. */
+ /** Deprecated. Use GetCpuProfile instead. */
static const CpuProfile* GetProfile(
int index,
Handle<Value> security_token = Handle<Value>());
+ /** Returns a profile by index. */
+ const CpuProfile* GetCpuProfile(
+ int index,
+ Handle<Value> security_token = Handle<Value>());
- /** Returns a profile by uid. */
+ /** Deprecated. Use FindProfile instead. */
static const CpuProfile* FindProfile(
unsigned uid,
Handle<Value> security_token = Handle<Value>());
+ /** Returns a profile by uid. */
+ const CpuProfile* FindCpuProfile(
+ unsigned uid,
+ Handle<Value> security_token = Handle<Value>());
+ /** Deprecated. Use StartCpuProfiling instead. */
+ static void StartProfiling(Handle<String> title, bool record_samples = false);
/**
* Starts collecting CPU profile. Title may be an empty string. It
* is allowed to have several profiles being collected at
@@ -198,22 +211,34 @@ class V8EXPORT CpuProfiler {
* |record_samples| parameter controls whether individual samples should
* be recorded in addition to the aggregated tree.
*/
- static void StartProfiling(Handle<String> title, bool record_samples = false);
+ void StartCpuProfiling(Handle<String> title, bool record_samples = false);
+ /** Deprecated. Use StopCpuProfiling instead. */
+ static const CpuProfile* StopProfiling(
+ Handle<String> title,
+ Handle<Value> security_token = Handle<Value>());
/**
* Stops collecting CPU profile with a given title and returns it.
* If the title given is empty, finishes the last profile started.
*/
- static const CpuProfile* StopProfiling(
+ const CpuProfile* StopCpuProfiling(
Handle<String> title,
Handle<Value> security_token = Handle<Value>());
+ /** Deprecated. Use DeleteAllCpuProfiles instead. */
+ static void DeleteAllProfiles();
/**
* Deletes all existing profiles, also cancelling all profiling
* activity. All previously returned pointers to profiles and their
* contents become invalid after this call.
*/
- static void DeleteAllProfiles();
+ void DeleteAllCpuProfiles();
+
+ private:
+ CpuProfiler();
+ ~CpuProfiler();
+ CpuProfiler(const CpuProfiler&);
+ CpuProfiler& operator=(const CpuProfiler&);
};
@@ -321,8 +346,8 @@ class V8EXPORT HeapSnapshot {
kJSON = 0 // See format description near 'Serialize' method.
};
- /** Returns heap snapshot type. */
- Type GetType() const;
+ /** Deprecated. Returns kFull. */
+ V8_DEPRECATED(Type GetType() const);
/** Returns heap snapshot UID (assigned by the profiler.) */
unsigned GetUid() const;
@@ -385,7 +410,8 @@ class V8EXPORT HeapSnapshot {
class RetainedObjectInfo;
/**
- * Interface for controlling heap profiling.
+ * Interface for controlling heap profiling. Instance of the
+ * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
*/
class V8EXPORT HeapProfiler {
public:
@@ -398,20 +424,28 @@ class V8EXPORT HeapProfiler {
typedef RetainedObjectInfo* (*WrapperInfoCallback)
(uint16_t class_id, Handle<Value> wrapper);
- /** Returns the number of snapshots taken. */
+ /** Deprecated. Use GetSnapshotCount instead. */
static int GetSnapshotsCount();
+ /** Returns the number of snapshots taken. */
+ int GetSnapshotCount();
- /** Returns a snapshot by index. */
+ /** Deprecated. Use GetHeapSnapshot instead. */
static const HeapSnapshot* GetSnapshot(int index);
+ /** Returns a snapshot by index. */
+ const HeapSnapshot* GetHeapSnapshot(int index);
- /** Returns a profile by uid. */
+ /** Deprecated. Use FindHeapSnapshot instead. */
static const HeapSnapshot* FindSnapshot(unsigned uid);
+ /** Returns a profile by uid. */
+ const HeapSnapshot* FindHeapSnapshot(unsigned uid);
+ /** Deprecated. Use GetObjectId instead. */
+ static SnapshotObjectId GetSnapshotObjectId(Handle<Value> value);
/**
* Returns SnapshotObjectId for a heap object referenced by |value| if
* it has been seen by the heap profiler, kUnknownObjectId otherwise.
*/
- static SnapshotObjectId GetSnapshotObjectId(Handle<Value> value);
+ SnapshotObjectId GetObjectId(Handle<Value> value);
/**
* A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
@@ -424,33 +458,42 @@ class V8EXPORT HeapProfiler {
* Callback interface for retrieving user friendly names of global objects.
*/
class ObjectNameResolver {
- public:
+ public:
/**
* Returns name to be used in the heap snapshot for given node. Returned
* string must stay alive until snapshot collection is completed.
*/
virtual const char* GetName(Handle<Object> object) = 0;
- protected:
+ protected:
virtual ~ObjectNameResolver() {}
};
+ /** Deprecated. Use TakeHeapSnapshot instead. */
+ static const HeapSnapshot* TakeSnapshot(
+ Handle<String> title,
+ HeapSnapshot::Type type = HeapSnapshot::kFull,
+ ActivityControl* control = NULL,
+ ObjectNameResolver* global_object_name_resolver = NULL);
/**
* Takes a heap snapshot and returns it. Title may be an empty string.
- * See HeapSnapshot::Type for types description.
*/
- static const HeapSnapshot* TakeSnapshot(
+ const HeapSnapshot* TakeHeapSnapshot(
Handle<String> title,
- HeapSnapshot::Type type = HeapSnapshot::kFull,
ActivityControl* control = NULL,
ObjectNameResolver* global_object_name_resolver = NULL);
+
+ /** Deprecated. Use StartTrackingHeapObjects instead. */
+ static void StartHeapObjectsTracking();
/**
* Starts tracking of heap objects population statistics. After calling
* this method, all heap objects relocations done by the garbage collector
* are being registered.
*/
- static void StartHeapObjectsTracking();
+ void StartTrackingHeapObjects();
+ /** Deprecated. Use GetHeapStats instead. */
+ static SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
/**
* Adds a new time interval entry to the aggregated statistics array. The
* time interval entry contains information on the current heap objects
@@ -460,28 +503,36 @@ class V8EXPORT HeapProfiler {
* HeapStatsUpdate structure instances.
* The return value of the function is the last seen heap object Id.
*
- * StartHeapObjectsTracking must be called before the first call to this
+ * StartTrackingHeapObjects must be called before the first call to this
* method.
*/
- static SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
+ SnapshotObjectId GetHeapStats(OutputStream* stream);
+ /** Deprecated. Use StopTrackingHeapObjects instead. */
+ static void StopHeapObjectsTracking();
/**
* Stops tracking of heap objects population statistics, cleans up all
* collected data. StartHeapObjectsTracking must be called again prior to
* calling PushHeapObjectsStats next time.
*/
- static void StopHeapObjectsTracking();
+ void StopTrackingHeapObjects();
+ /** Deprecated. Use DeleteAllHeapSnapshots instead. */
+ static void DeleteAllSnapshots();
/**
* Deletes all snapshots taken. All previously returned pointers to
* snapshots and their contents become invalid after this call.
*/
- static void DeleteAllSnapshots();
+ void DeleteAllHeapSnapshots();
- /** Binds a callback to embedder's class ID. */
+ /** Deprecated. Use SetWrapperClassInfoProvider instead. */
static void DefineWrapperClass(
uint16_t class_id,
WrapperInfoCallback callback);
+ /** Binds a callback to embedder's class ID. */
+ void SetWrapperClassInfoProvider(
+ uint16_t class_id,
+ WrapperInfoCallback callback);
/**
* Default value of persistent handle class ID. Must not be used to
@@ -490,11 +541,21 @@ class V8EXPORT HeapProfiler {
*/
static const uint16_t kPersistentHandleNoClassId = 0;
- /** Returns the number of currently existing persistent handles. */
+ /**
+ * Deprecated. Returns the number of currently existing persistent handles.
+ */
static int GetPersistentHandleCount();
- /** Returns memory used for profiler internal data and snapshots. */
+ /** Deprecated. Use GetHeapProfilerMemorySize instead. */
static size_t GetMemorySizeUsedByProfiler();
+ /** Returns memory used for profiler internal data and snapshots. */
+ size_t GetProfilerMemorySize();
+
+ private:
+ HeapProfiler();
+ ~HeapProfiler();
+ HeapProfiler(const HeapProfiler&);
+ HeapProfiler& operator=(const HeapProfiler&);
};
@@ -574,7 +635,7 @@ class V8EXPORT RetainedObjectInfo { // NOLINT
/**
* A struct for exporting HeapStats data from V8, using "push" model.
- * See HeapProfiler::PushHeapObjectsStats.
+ * See HeapProfiler::GetHeapStats.
*/
struct HeapStatsUpdate {
HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
index 329576fa9..9adb1c041 100644
--- a/deps/v8/include/v8.h
+++ b/deps/v8/include/v8.h
@@ -103,12 +103,14 @@ class Array;
class Boolean;
class BooleanObject;
class Context;
+class CpuProfiler;
class Data;
class Date;
class DeclaredAccessorDescriptor;
class External;
class Function;
class FunctionTemplate;
+class HeapProfiler;
class ImplementationUtilities;
class Int32;
class Integer;
@@ -3022,6 +3024,18 @@ class V8EXPORT Isolate {
*/
intptr_t AdjustAmountOfExternalAllocatedMemory(intptr_t change_in_bytes);
+ /**
+ * Returns heap profiler for this isolate. Will return NULL until the isolate
+ * is initialized.
+ */
+ HeapProfiler* GetHeapProfiler();
+
+ /**
+ * Returns CPU profiler for this isolate. Will return NULL until the isolate
+ * is initialized.
+ */
+ CpuProfiler* GetCpuProfiler();
+
private:
Isolate();
Isolate(const Isolate&);
@@ -4274,7 +4288,7 @@ class Internals {
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
- static const int kContextEmbedderDataIndex = 54;
+ static const int kContextEmbedderDataIndex = 55;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index dfa57654d..65663ba5c 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -477,14 +477,6 @@ void V8::SetAllowCodeGenerationFromStringsCallback(
}
-#ifdef DEBUG
-void ImplementationUtilities::ZapHandleRange(i::Object** begin,
- i::Object** end) {
- i::HandleScope::ZapRange(begin, end);
-}
-#endif
-
-
void V8::SetFlagsFromString(const char* str, int length) {
i::FlagList::SetFlagsFromString(str, length);
}
@@ -706,7 +698,7 @@ void HandleScope::Leave() {
i::HandleScope::DeleteExtensions(isolate_);
}
-#ifdef DEBUG
+#ifdef ENABLE_EXTRA_CHECKS
i::HandleScope::ZapRange(prev_next_, prev_limit_);
#endif
}
@@ -3197,7 +3189,7 @@ Local<String> v8::Object::ObjectProtoToString() {
i::Handle<i::Object> name(self->class_name(), isolate);
// Native implementation of Object.prototype.toString (v8natives.js):
- // var c = %ClassOf(this);
+ // var c = %_ClassOf(this);
// if (c === 'Arguments') c = 'Object';
// return "[object " + c + "]";
@@ -5807,6 +5799,20 @@ intptr_t V8::AdjustAmountOfExternalAllocatedMemory(intptr_t change_in_bytes) {
}
+HeapProfiler* Isolate::GetHeapProfiler() {
+ i::HeapProfiler* heap_profiler =
+ reinterpret_cast<i::Isolate*>(this)->heap_profiler();
+ return reinterpret_cast<HeapProfiler*>(heap_profiler);
+}
+
+
+CpuProfiler* Isolate::GetCpuProfiler() {
+ i::CpuProfiler* cpu_profiler =
+ reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
+ return reinterpret_cast<CpuProfiler*>(cpu_profiler);
+}
+
+
void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCPrologueCallback()")) return;
@@ -5979,6 +5985,14 @@ void Isolate::Exit() {
void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+ if (!isolate->IsInitialized()) {
+ heap_statistics->total_heap_size_ = 0;
+ heap_statistics->total_heap_size_executable_ = 0;
+ heap_statistics->total_physical_size_ = 0;
+ heap_statistics->used_heap_size_ = 0;
+ heap_statistics->heap_size_limit_ = 0;
+ return;
+ }
i::Heap* heap = isolate->heap();
heap_statistics->total_heap_size_ = heap->CommittedMemory();
heap_statistics->total_heap_size_executable_ =
@@ -6532,6 +6546,11 @@ int CpuProfiler::GetProfilesCount() {
}
+int CpuProfiler::GetProfileCount() {
+ return reinterpret_cast<i::CpuProfiler*>(this)->GetProfilesCount();
+}
+
+
const CpuProfile* CpuProfiler::GetProfile(int index,
Handle<Value> security_token) {
i::Isolate* isolate = i::Isolate::Current();
@@ -6545,6 +6564,15 @@ const CpuProfile* CpuProfiler::GetProfile(int index,
}
+const CpuProfile* CpuProfiler::GetCpuProfile(int index,
+ Handle<Value> security_token) {
+ return reinterpret_cast<const CpuProfile*>(
+ reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(
+ security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
+ index));
+}
+
+
const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
Handle<Value> security_token) {
i::Isolate* isolate = i::Isolate::Current();
@@ -6558,6 +6586,15 @@ const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
}
+const CpuProfile* CpuProfiler::FindCpuProfile(unsigned uid,
+ Handle<Value> security_token) {
+ return reinterpret_cast<const CpuProfile*>(
+ reinterpret_cast<i::CpuProfiler*>(this)->FindProfile(
+ security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
+ uid));
+}
+
+
void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling");
@@ -6567,6 +6604,12 @@ void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
}
+void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
+ reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
+ *Utils::OpenHandle(*title), record_samples);
+}
+
+
const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
Handle<Value> security_token) {
i::Isolate* isolate = i::Isolate::Current();
@@ -6580,6 +6623,15 @@ const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
}
+const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title,
+ Handle<Value> security_token) {
+ return reinterpret_cast<const CpuProfile*>(
+ reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
+ security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
+ *Utils::OpenHandle(*title)));
+}
+
+
void CpuProfiler::DeleteAllProfiles() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::DeleteAllProfiles");
@@ -6589,6 +6641,11 @@ void CpuProfiler::DeleteAllProfiles() {
}
+void CpuProfiler::DeleteAllCpuProfiles() {
+ reinterpret_cast<i::CpuProfiler*>(this)->DeleteAllProfiles();
+}
+
+
static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
return const_cast<i::HeapGraphEdge*>(
reinterpret_cast<const i::HeapGraphEdge*>(edge));
@@ -6708,11 +6765,11 @@ static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
void HeapSnapshot::Delete() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapSnapshot::Delete");
- if (i::HeapProfiler::GetSnapshotsCount() > 1) {
+ if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
ToInternal(this)->Delete();
} else {
// If this is the last snapshot, clean up all accessory data as well.
- i::HeapProfiler::DeleteAllSnapshots();
+ isolate->heap_profiler()->DeleteAllSnapshots();
}
}
@@ -6720,7 +6777,7 @@ void HeapSnapshot::Delete() {
HeapSnapshot::Type HeapSnapshot::GetType() const {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapSnapshot::GetType");
- return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
+ return kFull;
}
@@ -6797,7 +6854,12 @@ void HeapSnapshot::Serialize(OutputStream* stream,
int HeapProfiler::GetSnapshotsCount() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshotsCount");
- return i::HeapProfiler::GetSnapshotsCount();
+ return isolate->heap_profiler()->GetSnapshotsCount();
+}
+
+
+int HeapProfiler::GetSnapshotCount() {
+ return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
}
@@ -6805,7 +6867,13 @@ const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshot");
return reinterpret_cast<const HeapSnapshot*>(
- i::HeapProfiler::GetSnapshot(index));
+ isolate->heap_profiler()->GetSnapshot(index));
+}
+
+
+const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
+ return reinterpret_cast<const HeapSnapshot*>(
+ reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
}
@@ -6813,7 +6881,13 @@ const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::FindSnapshot");
return reinterpret_cast<const HeapSnapshot*>(
- i::HeapProfiler::FindSnapshot(uid));
+ isolate->heap_profiler()->FindSnapshot(uid));
+}
+
+
+const HeapSnapshot* HeapProfiler::FindHeapSnapshot(unsigned uid) {
+ return reinterpret_cast<const HeapSnapshot*>(
+ reinterpret_cast<i::HeapProfiler*>(this)->FindSnapshot(uid));
}
@@ -6821,7 +6895,13 @@ SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Value> value) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshotObjectId");
i::Handle<i::Object> obj = Utils::OpenHandle(*value);
- return i::HeapProfiler::GetSnapshotObjectId(obj);
+ return isolate->heap_profiler()->GetSnapshotObjectId(obj);
+}
+
+
+SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
+ i::Handle<i::Object> obj = Utils::OpenHandle(*value);
+ return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
}
@@ -6831,45 +6911,67 @@ const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
ObjectNameResolver* resolver) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::TakeSnapshot");
- i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
- switch (type) {
- case HeapSnapshot::kFull:
- internal_type = i::HeapSnapshot::kFull;
- break;
- default:
- UNREACHABLE();
- }
return reinterpret_cast<const HeapSnapshot*>(
- i::HeapProfiler::TakeSnapshot(
- *Utils::OpenHandle(*title), internal_type, control, resolver));
+ isolate->heap_profiler()->TakeSnapshot(
+ *Utils::OpenHandle(*title), control, resolver));
+}
+
+
+const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
+ Handle<String> title,
+ ActivityControl* control,
+ ObjectNameResolver* resolver) {
+ return reinterpret_cast<const HeapSnapshot*>(
+ reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
+ *Utils::OpenHandle(*title), control, resolver));
}
void HeapProfiler::StartHeapObjectsTracking() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::StartHeapObjectsTracking");
- i::HeapProfiler::StartHeapObjectsTracking();
+ isolate->heap_profiler()->StartHeapObjectsTracking();
+}
+
+
+void HeapProfiler::StartTrackingHeapObjects() {
+ reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking();
}
void HeapProfiler::StopHeapObjectsTracking() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::StopHeapObjectsTracking");
- i::HeapProfiler::StopHeapObjectsTracking();
+ isolate->heap_profiler()->StopHeapObjectsTracking();
+}
+
+
+void HeapProfiler::StopTrackingHeapObjects() {
+ reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
}
SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::PushHeapObjectsStats");
- return i::HeapProfiler::PushHeapObjectsStats(stream);
+ return isolate->heap_profiler()->PushHeapObjectsStats(stream);
+}
+
+
+SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
+ return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
}
void HeapProfiler::DeleteAllSnapshots() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapProfiler::DeleteAllSnapshots");
- i::HeapProfiler::DeleteAllSnapshots();
+ isolate->heap_profiler()->DeleteAllSnapshots();
+}
+
+
+void HeapProfiler::DeleteAllHeapSnapshots() {
+ reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
}
@@ -6880,6 +6982,13 @@ void HeapProfiler::DefineWrapperClass(uint16_t class_id,
}
+void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
+ WrapperInfoCallback callback) {
+ reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
+ callback);
+}
+
+
int HeapProfiler::GetPersistentHandleCount() {
i::Isolate* isolate = i::Isolate::Current();
return isolate->global_handles()->NumberOfGlobalHandles();
@@ -6887,7 +6996,13 @@ int HeapProfiler::GetPersistentHandleCount() {
size_t HeapProfiler::GetMemorySizeUsedByProfiler() {
- return i::HeapProfiler::GetMemorySizeUsedByProfiler();
+ return i::Isolate::Current()->heap_profiler()->GetMemorySizeUsedByProfiler();
+}
+
+
+size_t HeapProfiler::GetProfilerMemorySize() {
+ return reinterpret_cast<i::HeapProfiler*>(this)->
+ GetMemorySizeUsedByProfiler();
}
@@ -7082,7 +7197,7 @@ DeferredHandles::~DeferredHandles() {
isolate_->UnlinkDeferredHandles(this);
for (int i = 0; i < blocks_.length(); i++) {
-#ifdef DEBUG
+#ifdef ENABLE_EXTRA_CHECKS
HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
#endif
isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h
index ac6b8342c..d73646d99 100644
--- a/deps/v8/src/api.h
+++ b/deps/v8/src/api.h
@@ -294,6 +294,9 @@ MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor)
v8::internal::Handle<v8::internal::To> Utils::OpenHandle( \
const v8::From* that, bool allow_empty_handle) { \
EXTRA_CHECK(allow_empty_handle || that != NULL); \
+ EXTRA_CHECK(that == NULL || \
+ !(*reinterpret_cast<v8::internal::To**>( \
+ const_cast<v8::From*>(that)))->IsFailure()); \
return v8::internal::Handle<v8::internal::To>( \
reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
}
@@ -569,8 +572,8 @@ void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
#endif
blocks_.RemoveLast();
-#ifdef DEBUG
- v8::ImplementationUtilities::ZapHandleRange(block_start, block_limit);
+#ifdef ENABLE_EXTRA_CHECKS
+ internal::HandleScope::ZapRange(block_start, block_limit);
#endif
if (spare_ != NULL) {
DeleteArray(spare_);
diff --git a/deps/v8/src/apiutils.h b/deps/v8/src/apiutils.h
index 71c0e1c2c..9831f0866 100644
--- a/deps/v8/src/apiutils.h
+++ b/deps/v8/src/apiutils.h
@@ -67,10 +67,6 @@ class ImplementationUtilities {
// Introduce an alias for the handle scope data to allow non-friends
// to access the HandleScope data.
typedef v8::HandleScope::Data HandleScopeData;
-
-#ifdef DEBUG
- static void ZapHandleRange(internal::Object** begin, internal::Object** end);
-#endif
};
} // namespace v8
diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc
index 2946b355a..ebb9e1235 100644
--- a/deps/v8/src/arm/builtins-arm.cc
+++ b/deps/v8/src/arm/builtins-arm.cc
@@ -221,13 +221,12 @@ static void AllocateJSArray(MacroAssembler* masm,
__ add(elements_array_end,
elements_array_end,
Operand(array_size, ASR, kSmiTagSize));
- __ AllocateInNewSpace(
- elements_array_end,
- result,
- scratch1,
- scratch2,
- gc_required,
- static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
+ __ Allocate(elements_array_end,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
@@ -874,7 +873,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// r1: constructor function
// r2: initial map
__ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
- __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
+ __ Allocate(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
// Allocated the JSObject, now initialize the fields. Map is set to
// initial map and properties and elements are set to empty fixed array.
@@ -949,7 +948,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// r4: JSObject
// r5: start of next object
__ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
- __ AllocateInNewSpace(
+ __ Allocate(
r0,
r5,
r6,
@@ -1105,10 +1104,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE);
__ b(ge, &exit);
- // Symbols are "objects".
- __ CompareInstanceType(r1, r3, SYMBOL_TYPE);
- __ b(eq, &exit);
-
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ bind(&use_receiver);
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index b1ffaea14..d982f2706 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -61,6 +61,17 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
}
+void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { r2, r1, r0 };
+ descriptor->register_param_count_ = 3;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure);
+}
+
+
void TransitionElementsKindStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -84,7 +95,7 @@ static void InitializeArrayConstructorDescriptor(Isolate* isolate,
// stack param count needs (constructor pointer, and single argument)
descriptor->stack_parameter_count_ = &r0;
descriptor->register_params_ = registers;
- descriptor->extra_expression_stack_count_ = 1;
+ descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
descriptor->deoptimization_handler_ =
FUNCTION_ADDR(ArrayConstructor_StubFailure);
}
@@ -2623,8 +2634,8 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
OverwriteMode mode) {
Register left = r1;
Register right = r0;
- Register scratch1 = r7;
- Register scratch2 = r9;
+ Register scratch1 = r6;
+ Register scratch2 = r7;
Register scratch3 = r4;
ASSERT(smi_operands || (not_numbers != NULL));
@@ -2639,7 +2650,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
__ JumpIfNotSmi(right, miss);
}
- Register heap_number_map = r6;
+ Register heap_number_map = r9;
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
switch (op) {
@@ -4477,35 +4488,6 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
}
-void ArrayLengthStub::Generate(MacroAssembler* masm) {
- Label miss;
- Register receiver;
- if (kind() == Code::KEYED_LOAD_IC) {
- // ----------- S t a t e -------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
- __ cmp(r0, Operand(masm->isolate()->factory()->length_string()));
- __ b(ne, &miss);
- receiver = r1;
- } else {
- ASSERT(kind() == Code::LOAD_IC);
- // ----------- S t a t e -------------
- // -- r2 : name
- // -- lr : return address
- // -- r0 : receiver
- // -- sp[0] : receiver
- // -----------------------------------
- receiver = r0;
- }
-
- StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss);
- __ bind(&miss);
- StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
-}
-
-
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver;
@@ -4780,7 +4762,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
__ add(r9, r9, Operand(Heap::kArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ AllocateInNewSpace(r9, r0, r3, r4, &runtime, TAG_OBJECT);
+ __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT);
// r0 = address of new object(s) (tagged)
// r2 = argument count (tagged)
@@ -4956,13 +4938,8 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
__ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
// Do the allocation of both objects in one go.
- __ AllocateInNewSpace(r1,
- r0,
- r2,
- r3,
- &runtime,
- static_cast<AllocationFlags>(TAG_OBJECT |
- SIZE_IN_WORDS));
+ __ Allocate(r1, r0, r2, r3, &runtime,
+ static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Get the arguments boilerplate from the current native context.
__ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
@@ -5466,7 +5443,7 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
(JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
__ mov(r5, Operand(r1, LSR, kSmiTagSize + kSmiShiftSize));
__ add(r2, r5, Operand(objects_size));
- __ AllocateInNewSpace(
+ __ Allocate(
r2, // In: Size, in words.
r0, // Out: Start of allocation (tagged).
r3, // Scratch register.
@@ -7408,33 +7385,31 @@ void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
__ cmp(entity_name, tmp);
__ b(eq, done);
- if (i != kInlinedProbes - 1) {
- // Load the hole ready for use below:
- __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
+ // Load the hole ready for use below:
+ __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
- // Stop if found the property.
- __ cmp(entity_name, Operand(Handle<Name>(name)));
- __ b(eq, miss);
+ // Stop if found the property.
+ __ cmp(entity_name, Operand(Handle<Name>(name)));
+ __ b(eq, miss);
- Label good;
- __ cmp(entity_name, tmp);
- __ b(eq, &good);
+ Label good;
+ __ cmp(entity_name, tmp);
+ __ b(eq, &good);
- // Check if the entry name is not a unique name.
- __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
- __ ldrb(entity_name,
- FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
- __ tst(entity_name, Operand(kIsInternalizedMask));
- __ b(ne, &good);
- __ cmp(entity_name, Operand(SYMBOL_TYPE));
- __ b(ne, miss);
-
- __ bind(&good);
-
- // Restore the properties.
- __ ldr(properties,
- FieldMemOperand(receiver, JSObject::kPropertiesOffset));
- }
+ // Check if the entry name is not a unique name.
+ __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
+ __ ldrb(entity_name,
+ FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+ __ tst(entity_name, Operand(kIsInternalizedMask));
+ __ b(ne, &good);
+ __ cmp(entity_name, Operand(SYMBOL_TYPE));
+ __ b(ne, miss);
+
+ __ bind(&good);
+
+ // Restore the properties.
+ __ ldr(properties,
+ FieldMemOperand(receiver, JSObject::kPropertiesOffset));
}
const int spill_mask =
@@ -7987,6 +7962,9 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
int parameter_count_offset =
StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
__ ldr(r1, MemOperand(fp, parameter_count_offset));
+ if (function_mode_ == JS_FUNCTION_STUB_MODE) {
+ __ add(r1, r1, Operand(1));
+ }
masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
__ mov(r1, Operand(r1, LSL, kPointerSizeLog2));
__ add(sp, sp, r1);
diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index ff97ab509..1c829469c 100644
--- a/deps/v8/src/arm/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -207,7 +207,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
// Use lr as a temporary register.
__ mov(lr, Operand(r5, LSL, 2));
__ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize));
- __ AllocateInNewSpace(lr, r6, r7, r9, &gc_required, DOUBLE_ALIGNMENT);
+ __ Allocate(lr, r6, r7, r9, &gc_required, DOUBLE_ALIGNMENT);
// r6: destination FixedDoubleArray, not tagged as heap object.
// Set destination FixedDoubleArray's length and map.
@@ -348,7 +348,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
// Allocate new FixedArray.
__ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
__ add(r0, r0, Operand(r5, LSL, 1));
- __ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
+ __ Allocate(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
// r6: destination FixedArray, not tagged as heap object
// Set destination FixedDoubleArray's length and map.
__ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
@@ -691,7 +691,7 @@ void Code::PatchPlatformCodeAge(byte* sequence,
uint32_t young_length;
byte* young_sequence = GetNoCodeAgeSequence(&young_length);
if (age == kNoAge) {
- memcpy(sequence, young_sequence, young_length);
+ CopyBytes(sequence, young_sequence, young_length);
CPU::FlushICache(sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(age, parity);
diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc
index 1df1649d3..6086645db 100644
--- a/deps/v8/src/arm/full-codegen-arm.cc
+++ b/deps/v8/src/arm/full-codegen-arm.cc
@@ -2764,28 +2764,6 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
}
-void FullCodeGenerator::EmitIsSymbol(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(r0, if_false);
- __ CompareObjectType(r0, r1, r2, SYMBOL_TYPE);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1);
@@ -4292,6 +4270,10 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
__ tst(r1, Operand(1 << Map::kIsUndetectable));
Split(eq, if_true, if_false, fall_through);
+ } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ __ JumpIfSmi(r0, if_false);
+ __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
+ Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
__ CompareRoot(r0, Heap::kTrueValueRootIndex);
__ b(eq, if_true);
@@ -4324,10 +4306,6 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ CompareRoot(r0, Heap::kNullValueRootIndex);
__ b(eq, if_true);
}
- if (FLAG_harmony_symbols) {
- __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
- __ b(eq, if_true);
- }
// Check for JS objects => true.
__ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
__ b(lt, if_false);
diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc
index 38884ce0a..f2b65efe8 100644
--- a/deps/v8/src/arm/lithium-arm.cc
+++ b/deps/v8/src/arm/lithium-arm.cc
@@ -871,6 +871,35 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LInstruction* instr = current->CompileToLithium(this);
if (instr != NULL) {
+#if DEBUG
+ // Make sure that the lithium instruction has either no fixed register
+ // constraints in temps or the result OR no uses that are only used at
+ // start. If this invariant doesn't hold, the register allocator can decide
+ // to insert a split of a range immediately before the instruction due to an
+ // already allocated register needing to be used for the instruction's fixed
+ // register constraint. In this case, The register allocator won't see an
+ // interference between the split child and the use-at-start (it would if
+ // the it was just a plain use), so it is free to move the split child into
+ // the same register that is used for the use-at-start.
+ // See https://code.google.com/p/chromium/issues/detail?id=201590
+ if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
+ int fixed = 0;
+ int used_at_start = 0;
+ for (UseIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->IsUsedAtStart()) ++used_at_start;
+ }
+ if (instr->Output() != NULL) {
+ if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
+ }
+ for (TempIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->HasFixedPolicy()) ++fixed;
+ }
+ ASSERT(fixed == 0 || used_at_start == 0);
+ }
+#endif
+
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -1115,7 +1144,7 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
return DefineFixedDouble(result, d2);
} else {
- LOperand* input = UseRegisterAtStart(instr->value());
+ LOperand* input = UseRegister(instr->value());
LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
@@ -1711,12 +1740,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
-LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
- LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LJSArrayLength(array));
-}
-
-
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
@@ -1823,11 +1846,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
return AssignEnvironment(DefineAsRegister(res));
} else {
ASSERT(to.IsInteger32());
- LOperand* value = UseRegisterAtStart(instr->value());
+ LOperand* value = NULL;
LInstruction* res = NULL;
if (instr->value()->type().IsSmi()) {
+ value = UseRegisterAtStart(instr->value());
res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
} else {
+ value = UseRegister(instr->value());
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
@@ -2205,7 +2230,7 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind(
LOperand* new_map_reg = TempRegister();
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
- return DefineSameAsFirst(result);
+ return result;
} else if (FLAG_compiled_transitions) {
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, NULL, NULL);
diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h
index f49e8ce4f..207faf46e 100644
--- a/deps/v8/src/arm/lithium-arm.h
+++ b/deps/v8/src/arm/lithium-arm.h
@@ -120,7 +120,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@@ -1165,19 +1164,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
};
-class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LJSArrayLength(LOperand* value) {
- inputs_[0] = value;
- }
-
- LOperand* value() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
- DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
-};
-
-
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {
@@ -2114,7 +2100,7 @@ class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
};
-class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
+class LTransitionElementsKind: public LTemplateInstruction<0, 1, 2> {
public:
LTransitionElementsKind(LOperand* object,
LOperand* new_map_temp,
diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc
index 3ad86cfed..7bb3535ff 100644
--- a/deps/v8/src/arm/lithium-codegen-arm.cc
+++ b/deps/v8/src/arm/lithium-codegen-arm.cc
@@ -239,7 +239,7 @@ bool LCodeGen::GeneratePrologue() {
__ str(r0, target);
// Update the write barrier. This clobbers r3 and r0.
__ RecordWriteContextSlot(
- cp, target.offset(), r0, r3, kLRHasBeenSaved, kSaveFPRegs);
+ cp, target.offset(), r0, r3, GetLinkRegisterState(), kSaveFPRegs);
}
}
Comment(";;; End allocate local context");
@@ -1918,13 +1918,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
-void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
- Register result = ToRegister(instr->result());
- Register array = ToRegister(instr->value());
- __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
-}
-
-
void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
@@ -2301,6 +2294,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ bind(&not_string);
}
+ if (expected.Contains(ToBooleanStub::SYMBOL)) {
+ // Symbol value -> true.
+ __ CompareInstanceType(map, ip, SYMBOL_TYPE);
+ __ b(eq, true_label);
+ }
+
if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
CpuFeatureScope scope(masm(), VFP2);
// heap number -> false iff +0, -0, or NaN.
@@ -3075,7 +3074,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
target.offset(),
value,
scratch,
- kLRHasBeenSaved,
+ GetLinkRegisterState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4367,7 +4366,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
HeapObject::kMapOffset,
scratch,
temp,
- kLRHasBeenSaved,
+ GetLinkRegisterState(),
kSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
@@ -4386,7 +4385,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
offset,
value,
scratch,
- kLRHasBeenSaved,
+ GetLinkRegisterState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4401,7 +4400,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
offset,
value,
object,
- kLRHasBeenSaved,
+ GetLinkRegisterState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4602,7 +4601,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
__ RecordWrite(elements,
key,
value,
- kLRHasBeenSaved,
+ GetLinkRegisterState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4654,7 +4653,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
__ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
// Write barrier.
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
- scratch, kLRHasBeenSaved, kDontSaveFPRegs);
+ scratch, GetLinkRegisterState(), kDontSaveFPRegs);
} else if (FLAG_compiled_transitions) {
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
__ Move(r0, object_reg);
@@ -4897,10 +4896,11 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
// Convert unsigned integer with specified number of leading zeroes in binary
// representation to IEEE 754 double.
-// Integer to convert is passed in register hiword.
+// Integer to convert is passed in register src.
// Resulting double is returned in registers hiword:loword.
// This functions does not work correctly for 0.
static void GenerateUInt2Double(MacroAssembler* masm,
+ Register src,
Register hiword,
Register loword,
Register scratch,
@@ -4914,13 +4914,13 @@ static void GenerateUInt2Double(MacroAssembler* masm,
kBitsPerInt - mantissa_shift_for_hi_word;
masm->mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift));
if (mantissa_shift_for_hi_word > 0) {
- masm->mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word));
+ masm->mov(loword, Operand(src, LSL, mantissa_shift_for_lo_word));
masm->orr(hiword, scratch,
- Operand(hiword, LSR, mantissa_shift_for_hi_word));
+ Operand(src, LSR, mantissa_shift_for_hi_word));
} else {
masm->mov(loword, Operand::Zero());
masm->orr(hiword, scratch,
- Operand(hiword, LSL, -mantissa_shift_for_hi_word));
+ Operand(src, LSL, -mantissa_shift_for_hi_word));
}
// If least significant bit of biased exponent was not 1 it was corrupted
@@ -4969,17 +4969,17 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr,
__ vmov(flt_scratch, src);
__ vcvt_f64_u32(dbl_scratch, flt_scratch);
} else {
- Label no_leading_zero, done;
+ Label no_leading_zero, convert_done;
__ tst(src, Operand(0x80000000));
__ b(ne, &no_leading_zero);
// Integer has one leading zeros.
- GenerateUInt2Double(masm(), sfpd_hi, sfpd_lo, r9, 1);
- __ b(&done);
+ GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, r9, 1);
+ __ b(&convert_done);
__ bind(&no_leading_zero);
- GenerateUInt2Double(masm(), sfpd_hi, sfpd_lo, r9, 0);
- __ b(&done);
+ GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, r9, 0);
+ __ bind(&convert_done);
}
}
@@ -4996,10 +4996,18 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr,
// TODO(3095996): Put a valid pointer value in the stack slot where the result
// register is stored, as this register is in the pointer map, but contains an
// integer value.
+ if (!CpuFeatures::IsSupported(VFP2)) {
+ // Preserve sfpd_lo.
+ __ mov(r9, sfpd_lo);
+ }
__ mov(ip, Operand::Zero());
__ StoreToSafepointRegisterSlot(ip, dst);
CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
__ Move(dst, r0);
+ if (!CpuFeatures::IsSupported(VFP2)) {
+ // Restore sfpd_lo.
+ __ mov(sfpd_lo, r9);
+ }
__ sub(dst, dst, Operand(kHeapObjectTag));
// Done. Put the value in dbl_scratch into the value of the allocated heap
@@ -5671,12 +5679,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
__ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
- __ AllocateInNewSpace(size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- flags);
+ __ Allocate(size,
+ result,
+ scratch,
+ scratch2,
+ deferred->entry(),
+ flags);
}
__ bind(deferred->exit());
@@ -6074,6 +6082,11 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ tst(ip, Operand(1 << Map::kIsUndetectable));
final_branch_condition = eq;
+ } else if (type_name->Equals(heap()->symbol_string())) {
+ __ JumpIfSmi(input, false_label);
+ __ CompareObjectType(input, input, scratch, SYMBOL_TYPE);
+ final_branch_condition = eq;
+
} else if (type_name->Equals(heap()->boolean_string())) {
__ CompareRoot(input, Heap::kTrueValueRootIndex);
__ b(eq, true_label);
@@ -6108,15 +6121,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ CompareRoot(input, Heap::kNullValueRootIndex);
__ b(eq, true_label);
}
- if (FLAG_harmony_symbols) {
- __ CompareObjectType(input, input, scratch, SYMBOL_TYPE);
- __ b(eq, true_label);
- __ CompareInstanceType(input, scratch,
- FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- } else {
- __ CompareObjectType(input, input, scratch,
- FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- }
+ __ CompareObjectType(input, input, scratch,
+ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
__ b(lt, false_label);
__ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
__ b(gt, false_label);
diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h
index d1f712ab8..686241db7 100644
--- a/deps/v8/src/arm/lithium-codegen-arm.h
+++ b/deps/v8/src/arm/lithium-codegen-arm.h
@@ -87,6 +87,10 @@ class LCodeGen BASE_EMBEDDED {
return !NeedsEagerFrame() && info()->is_deferred_calling();
}
+ LinkRegisterStatus GetLinkRegisterState() const {
+ return frame_is_built_ ? kLRHasBeenSaved : kLRHasNotBeenSaved;
+ }
+
// Support for converting LOperands to assembler types.
// LOperand must be a register.
Register ToRegister(LOperand* op) const;
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index e0e77cfd3..bacf570c3 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -708,15 +708,14 @@ void MacroAssembler::Ldrd(Register dst1, Register dst2,
const MemOperand& src, Condition cond) {
ASSERT(src.rm().is(no_reg));
ASSERT(!dst1.is(lr)); // r14.
- ASSERT_EQ(0, dst1.code() % 2);
- ASSERT_EQ(dst1.code() + 1, dst2.code());
// V8 does not use this addressing mode, so the fallback code
// below doesn't support it yet.
ASSERT((src.am() != PreIndex) && (src.am() != NegPreIndex));
// Generate two ldr instructions if ldrd is not available.
- if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
+ if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size() &&
+ (dst1.code() % 2 == 0) && (dst1.code() + 1 == dst2.code())) {
CpuFeatureScope scope(this, ARMv7);
ldrd(dst1, dst2, src, cond);
} else {
@@ -750,15 +749,14 @@ void MacroAssembler::Strd(Register src1, Register src2,
const MemOperand& dst, Condition cond) {
ASSERT(dst.rm().is(no_reg));
ASSERT(!src1.is(lr)); // r14.
- ASSERT_EQ(0, src1.code() % 2);
- ASSERT_EQ(src1.code() + 1, src2.code());
// V8 does not use this addressing mode, so the fallback code
// below doesn't support it yet.
ASSERT((dst.am() != PreIndex) && (dst.am() != NegPreIndex));
// Generate two str instructions if strd is not available.
- if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
+ if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size() &&
+ (src1.code() % 2 == 0) && (src1.code() + 1 == src2.code())) {
CpuFeatureScope scope(this, ARMv7);
strd(src1, src2, dst, cond);
} else {
@@ -1671,13 +1669,12 @@ void MacroAssembler::Allocate(int object_size,
}
-void MacroAssembler::AllocateInNewSpace(Register object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags) {
- ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
+void MacroAssembler::Allocate(Register object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags) {
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1703,20 +1700,20 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
// The values must be adjacent in memory to allow the use of LDM.
// Also, assert that the registers are numbered such that the values
// are loaded in the correct order.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
intptr_t top =
- reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+ reinterpret_cast<intptr_t>(allocation_top.address());
intptr_t limit =
- reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+ reinterpret_cast<intptr_t>(allocation_limit.address());
ASSERT((limit - top) == kPointerSize);
ASSERT(result.code() < ip.code());
// Set up allocation top address.
Register topaddr = scratch1;
- mov(topaddr, Operand(new_space_allocation_top));
+ mov(topaddr, Operand(allocation_top));
// This code stores a temporary value in ip. This is OK, as the code below
// does not need ip for implicit literal generation.
@@ -1739,6 +1736,7 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
if ((flags & DOUBLE_ALIGNMENT) != 0) {
// Align the next allocation. Storing the filler map without checking top is
// always safe because the limit of the heap is always aligned.
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC);
Label aligned;
@@ -1809,12 +1807,12 @@ void MacroAssembler::AllocateTwoByteString(Register result,
and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
// Allocate two-byte string in new space.
- AllocateInNewSpace(scratch1,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(scratch1,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
InitializeNewString(result,
@@ -1840,12 +1838,12 @@ void MacroAssembler::AllocateAsciiString(Register result,
and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
// Allocate ASCII string in new space.
- AllocateInNewSpace(scratch1,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(scratch1,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
InitializeNewString(result,
@@ -2499,9 +2497,9 @@ void MacroAssembler::TryInt32Floor(Register result,
void MacroAssembler::ECMAConvertNumberToInt32(Register source,
Register result,
- Register scratch,
- Register input_high,
Register input_low,
+ Register input_high,
+ Register scratch,
DwVfpRegister double_scratch1,
DwVfpRegister double_scratch2) {
if (CpuFeatures::IsSupported(VFP2)) {
@@ -2578,24 +2576,26 @@ void MacroAssembler::ECMAToInt32NoVFP(Register result,
Ubfx(scratch, input_high,
HeapNumber::kExponentShift, HeapNumber::kExponentBits);
- // Load scratch with exponent - 1. This is faster than loading
- // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value.
- sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
+ // Load scratch with exponent.
+ sub(scratch, scratch, Operand(HeapNumber::kExponentBias));
// If exponent is negative, 0 < input < 1, the result is 0.
// If exponent is greater than or equal to 84, the 32 less significant
// bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
// the result is 0.
// This test also catch Nan and infinities which also return 0.
- // Compare exponent with 84 (compare exponent - 1 with 83).
- cmp(scratch, Operand(83));
+ cmp(scratch, Operand(84));
// We do an unsigned comparison so negative numbers are treated as big
// positive number and the two tests above are done in one test.
b(hs, &out_of_range);
- // Load scratch with 20 - exponent (load with 19 - (exponent - 1)).
- rsb(scratch, scratch, Operand(19), SetCC);
+ // Load scratch with 20 - exponent.
+ rsb(scratch, scratch, Operand(20), SetCC);
b(mi, &both);
+ // Test 0 and -0.
+ bic(result, input_high, Operand(HeapNumber::kSignMask));
+ orr(result, result, Operand(input_low), SetCC);
+ b(eq, &done);
// 0 <= exponent <= 20, shift only input_high.
// Scratch contains: 20 - exponent.
Ubfx(result, input_high,
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index 5cbe995d7..958fcacb3 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -679,12 +679,12 @@ class MacroAssembler: public Assembler {
Label* gc_required,
AllocationFlags flags);
- void AllocateInNewSpace(Register object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(Register object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags);
// Undo allocation in new space. The object passed and objects allocated after
// it will no longer be allocated. The caller must make sure that no pointers
@@ -960,9 +960,9 @@ class MacroAssembler: public Assembler {
// Exits with 'result' holding the answer.
void ECMAConvertNumberToInt32(Register source,
Register result,
- Register scratch,
- Register input_high,
Register input_low,
+ Register input_high,
+ Register scratch,
DwVfpRegister double_scratch1,
DwVfpRegister double_scratch2);
diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index b7bc83905..2551e14e4 100644
--- a/deps/v8/src/arm/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -112,8 +112,8 @@ void ArmDebugger::Stop(Instruction* instr) {
ASSERT(msg != NULL);
// Update this stop description.
- if (isWatchedStop(code) && !watched_stops[code].desc) {
- watched_stops[code].desc = msg;
+ if (isWatchedStop(code) && !watched_stops_[code].desc) {
+ watched_stops_[code].desc = msg;
}
if (strlen(msg) > 0) {
@@ -141,8 +141,8 @@ void ArmDebugger::Stop(Instruction* instr) {
char* msg = *reinterpret_cast<char**>(sim_->get_pc()
+ Instruction::kInstrSize);
// Update this stop description.
- if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
- sim_->watched_stops[code].desc = msg;
+ if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
+ sim_->watched_stops_[code].desc = msg;
}
// Print the stop message and code if it is not the default code.
if (code != kMaxStopCode) {
@@ -1880,14 +1880,14 @@ bool Simulator::isEnabledStop(uint32_t code) {
ASSERT(code <= kMaxStopCode);
// Unwatched stops are always enabled.
return !isWatchedStop(code) ||
- !(watched_stops[code].count & kStopDisabledBit);
+ !(watched_stops_[code].count & kStopDisabledBit);
}
void Simulator::EnableStop(uint32_t code) {
ASSERT(isWatchedStop(code));
if (!isEnabledStop(code)) {
- watched_stops[code].count &= ~kStopDisabledBit;
+ watched_stops_[code].count &= ~kStopDisabledBit;
}
}
@@ -1895,7 +1895,7 @@ void Simulator::EnableStop(uint32_t code) {
void Simulator::DisableStop(uint32_t code) {
ASSERT(isWatchedStop(code));
if (isEnabledStop(code)) {
- watched_stops[code].count |= kStopDisabledBit;
+ watched_stops_[code].count |= kStopDisabledBit;
}
}
@@ -1903,13 +1903,13 @@ void Simulator::DisableStop(uint32_t code) {
void Simulator::IncreaseStopCounter(uint32_t code) {
ASSERT(code <= kMaxStopCode);
ASSERT(isWatchedStop(code));
- if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
+ if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
PrintF("Stop counter for code %i has overflowed.\n"
"Enabling this code and reseting the counter to 0.\n", code);
- watched_stops[code].count = 0;
+ watched_stops_[code].count = 0;
EnableStop(code);
} else {
- watched_stops[code].count++;
+ watched_stops_[code].count++;
}
}
@@ -1921,12 +1921,12 @@ void Simulator::PrintStopInfo(uint32_t code) {
PrintF("Stop not watched.");
} else {
const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
- int32_t count = watched_stops[code].count & ~kStopDisabledBit;
+ int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
// Don't print the state of unused breakpoints.
if (count != 0) {
- if (watched_stops[code].desc) {
+ if (watched_stops_[code].desc) {
PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
- code, code, state, count, watched_stops[code].desc);
+ code, code, state, count, watched_stops_[code].desc);
} else {
PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
code, code, state, count);
diff --git a/deps/v8/src/arm/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h
index 907a59066..b918ecf96 100644
--- a/deps/v8/src/arm/simulator-arm.h
+++ b/deps/v8/src/arm/simulator-arm.h
@@ -414,14 +414,14 @@ class Simulator {
static const uint32_t kStopDisabledBit = 1 << 31;
// A stop is enabled, meaning the simulator will stop when meeting the
- // instruction, if bit 31 of watched_stops[code].count is unset.
- // The value watched_stops[code].count & ~(1 << 31) indicates how many times
+ // instruction, if bit 31 of watched_stops_[code].count is unset.
+ // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
// the breakpoint was hit or gone through.
struct StopCountAndDesc {
uint32_t count;
char* desc;
};
- StopCountAndDesc watched_stops[kNumOfWatchedStops];
+ StopCountAndDesc watched_stops_[kNumOfWatchedStops];
};
diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc
index 3350c56c1..f2d45e190 100644
--- a/deps/v8/src/arm/stub-cache-arm.cc
+++ b/deps/v8/src/arm/stub-cache-arm.cc
@@ -423,7 +423,7 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
// registers have their original values.
void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
@@ -436,16 +436,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// r0 : value
Label exit;
- LookupResult lookup(masm->isolate());
- object->Lookup(*name, &lookup);
- if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
- // In sloppy mode, we could just return the value and be done. However, we
- // might be in strict mode, where we have to throw. Since we cannot tell,
- // go into slow case unconditionally.
- __ jmp(miss_label);
- return;
- }
-
// Check that the map of the object hasn't changed.
CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
: REQUIRE_EXACT_MAP;
@@ -460,8 +450,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Check that we are allowed to write this.
if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
JSObject* holder;
- if (lookup.IsFound()) {
- holder = lookup.holder();
+ // holder == object indicates that no property was found.
+ if (lookup->holder() != *object) {
+ holder = lookup->holder();
} else {
// Find the top object.
holder = *object;
@@ -469,8 +460,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject());
}
- CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, miss_restore_name);
+ Register holder_reg = CheckPrototypes(
+ object, receiver_reg, Handle<JSObject>(holder), name_reg,
+ scratch1, scratch2, name, miss_restore_name);
+ // If no property was found, and the holder (the last object in the
+ // prototype chain) is in slow mode, we need to do a negative lookup on the
+ // holder.
+ if (lookup->holder() == *object &&
+ !holder->HasFastProperties() &&
+ !holder->IsJSGlobalProxy() &&
+ !holder->IsJSGlobalObject()) {
+ GenerateDictionaryNegativeLookup(
+ masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
+ }
}
// Stub never generated for non-global objects that require access
@@ -492,6 +494,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
return;
}
+ int index;
if (!transition.is_null()) {
// Update the map of the object.
__ mov(scratch1, Operand(transition));
@@ -507,6 +510,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kDontSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
+ index = transition->instance_descriptors()->GetFieldIndex(
+ transition->LastAdded());
+ } else {
+ index = lookup->GetFieldIndex().field_index();
}
// Adjust for the number of properties stored in the object. Even in the
@@ -2391,6 +2398,12 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
// Check that the object is a symbol.
__ CompareObjectType(r1, r1, r3, SYMBOL_TYPE);
__ b(ne, &miss);
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss);
+ CheckPrototypes(
+ Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
+ r0, holder, r3, r1, r4, name, &miss);
break;
case NUMBER_CHECK: {
@@ -2982,7 +2995,7 @@ Handle<Code> ConstructStubCompiler::CompileConstructStub(
__ cmp(r3, Operand(instance_size >> kPointerSizeLog2));
__ Check(eq, "Instance size of initial map changed.");
#endif
- __ AllocateInNewSpace(r3, r4, r5, r6, &generic_stub_call, SIZE_IN_WORDS);
+ __ Allocate(r3, r4, r5, r6, &generic_stub_call, SIZE_IN_WORDS);
// Allocated the JSObject, now initialize the fields. Map is set to initial
// map and properties and elements are set to empty fixed array.
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index 7cf744bed..936d00801 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -38,22 +38,21 @@ var visited_arrays = new InternalArray();
// Gets a sorted array of array keys. Useful for operations on sparse
// arrays. Dupes have not been removed.
-function GetSortedArrayKeys(array, intervals) {
- var length = intervals.length;
- var keys = [];
- for (var k = 0; k < length; k++) {
- var key = intervals[k];
- if (key < 0) {
- var j = -1 - key;
- var limit = j + intervals[++k];
- for (; j < limit; j++) {
- var e = array[j];
- if (!IS_UNDEFINED(e) || j in array) {
- keys.push(j);
- }
+function GetSortedArrayKeys(array, indices) {
+ var keys = new InternalArray();
+ if (IS_NUMBER(indices)) {
+ // It's an interval
+ var limit = indices;
+ for (var i = 0; i < limit; ++i) {
+ var e = array[i];
+ if (!IS_UNDEFINED(e) || i in array) {
+ keys.push(i);
}
- } else {
- // The case where key is undefined also ends here.
+ }
+ } else {
+ var length = indices.length;
+ for (var k = 0; k < length; ++k) {
+ var key = indices[k];
if (!IS_UNDEFINED(key)) {
var e = array[key];
if (!IS_UNDEFINED(e) || key in array) {
@@ -61,8 +60,8 @@ function GetSortedArrayKeys(array, intervals) {
}
}
}
+ %_CallFunction(keys, function(a, b) { return a - b; }, ArraySort);
}
- %_CallFunction(keys, function(a, b) { return a - b; }, ArraySort);
return keys;
}
@@ -217,34 +216,21 @@ function ConvertToLocaleString(e) {
// special array operations to handle sparse arrays in a sensible fashion.
function SmartSlice(array, start_i, del_count, len, deleted_elements) {
// Move deleted elements to a new array (the return value from splice).
- // Intervals array can contain keys and intervals. See comment in Concat.
- var intervals = %GetArrayKeys(array, start_i + del_count);
- var length = intervals.length;
- for (var k = 0; k < length; k++) {
- var key = intervals[k];
- if (key < 0) {
- var j = -1 - key;
- var interval_limit = j + intervals[++k];
- if (j < start_i) {
- j = start_i;
- }
- for (; j < interval_limit; j++) {
- // ECMA-262 15.4.4.12 line 10. The spec could also be
- // interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[j];
- if (!IS_UNDEFINED(current) || j in array) {
- deleted_elements[j - start_i] = current;
- }
+ var indices = %GetArrayKeys(array, start_i + del_count);
+ if (IS_NUMBER(indices)) {
+ var limit = indices;
+ for (var i = start_i; i < limit; ++i) {
+ var current = array[i];
+ if (!IS_UNDEFINED(current) || i in array) {
+ deleted_elements[i - start_i] = current;
}
- } else {
+ }
+ } else {
+ var length = indices.length;
+ for (var k = 0; k < length; ++k) {
+ var key = indices[k];
if (!IS_UNDEFINED(key)) {
if (key >= start_i) {
- // ECMA-262 15.4.4.12 line 10. The spec could also be
- // interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
var current = array[key];
if (!IS_UNDEFINED(current) || key in array) {
deleted_elements[key - start_i] = current;
@@ -261,50 +247,32 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) {
function SmartMove(array, start_i, del_count, len, num_additional_args) {
// Move data to new array.
var new_array = new InternalArray(len - del_count + num_additional_args);
- var intervals = %GetArrayKeys(array, len);
- var length = intervals.length;
- for (var k = 0; k < length; k++) {
- var key = intervals[k];
- if (key < 0) {
- var j = -1 - key;
- var interval_limit = j + intervals[++k];
- while (j < start_i && j < interval_limit) {
- // The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
- // KJS in consulting the prototype.
- var current = array[j];
- if (!IS_UNDEFINED(current) || j in array) {
- new_array[j] = current;
- }
- j++;
+ var indices = %GetArrayKeys(array, len);
+ if (IS_NUMBER(indices)) {
+ var limit = indices;
+ for (var i = 0; i < start_i && i < limit; ++i) {
+ var current = array[i];
+ if (!IS_UNDEFINED(current) || i in array) {
+ new_array[i] = current;
}
- j = start_i + del_count;
- while (j < interval_limit) {
- // ECMA-262 15.4.4.12 lines 24 and 41. The spec could also be
- // interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[j];
- if (!IS_UNDEFINED(current) || j in array) {
- new_array[j - del_count + num_additional_args] = current;
- }
- j++;
+ }
+ for (var i = start_i + del_count; i < limit; ++i) {
+ var current = array[i];
+ if (!IS_UNDEFINED(current) || i in array) {
+ new_array[i - del_count + num_additional_args] = current;
}
- } else {
+ }
+ } else {
+ var length = indices.length;
+ for (var k = 0; k < length; ++k) {
+ var key = indices[k];
if (!IS_UNDEFINED(key)) {
if (key < start_i) {
- // The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
- // KJS in consulting the prototype.
var current = array[key];
if (!IS_UNDEFINED(current) || key in array) {
new_array[key] = current;
}
} else if (key >= start_i + del_count) {
- // ECMA-262 15.4.4.12 lines 24 and 41. The spec could also
- // be interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
var current = array[key];
if (!IS_UNDEFINED(current) || key in array) {
new_array[key - del_count + num_additional_args] = current;
@@ -887,24 +855,22 @@ function ArraySort(comparefn) {
var max = 0;
for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
var indices = %GetArrayKeys(proto, length);
- if (indices.length > 0) {
- if (indices[0] == -1) {
- // It's an interval.
- var proto_length = indices[1];
- for (var i = 0; i < proto_length; i++) {
- if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) {
- obj[i] = proto[i];
- if (i >= max) { max = i + 1; }
- }
+ if (IS_NUMBER(indices)) {
+ // It's an interval.
+ var proto_length = indices;
+ for (var i = 0; i < proto_length; i++) {
+ if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) {
+ obj[i] = proto[i];
+ if (i >= max) { max = i + 1; }
}
- } else {
- for (var i = 0; i < indices.length; i++) {
- var index = indices[i];
- if (!IS_UNDEFINED(index) &&
- !obj.hasOwnProperty(index) && proto.hasOwnProperty(index)) {
- obj[index] = proto[index];
- if (index >= max) { max = index + 1; }
- }
+ }
+ } else {
+ for (var i = 0; i < indices.length; i++) {
+ var index = indices[i];
+ if (!IS_UNDEFINED(index) &&
+ !obj.hasOwnProperty(index) && proto.hasOwnProperty(index)) {
+ obj[index] = proto[index];
+ if (index >= max) { max = index + 1; }
}
}
}
@@ -918,22 +884,20 @@ function ArraySort(comparefn) {
var ShadowPrototypeElements = function(obj, from, to) {
for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
var indices = %GetArrayKeys(proto, to);
- if (indices.length > 0) {
- if (indices[0] == -1) {
- // It's an interval.
- var proto_length = indices[1];
- for (var i = from; i < proto_length; i++) {
- if (proto.hasOwnProperty(i)) {
- obj[i] = void 0;
- }
+ if (IS_NUMBER(indices)) {
+ // It's an interval.
+ var proto_length = indices;
+ for (var i = from; i < proto_length; i++) {
+ if (proto.hasOwnProperty(i)) {
+ obj[i] = void 0;
}
- } else {
- for (var i = 0; i < indices.length; i++) {
- var index = indices[i];
- if (!IS_UNDEFINED(index) && from <= index &&
- proto.hasOwnProperty(index)) {
- obj[index] = void 0;
- }
+ }
+ } else {
+ for (var i = 0; i < indices.length; i++) {
+ var index = indices[i];
+ if (!IS_UNDEFINED(index) && from <= index &&
+ proto.hasOwnProperty(index)) {
+ obj[index] = void 0;
}
}
}
@@ -1284,18 +1248,15 @@ function ArrayIndexOf(element, index) {
var min = index;
var max = length;
if (UseSparseVariant(this, length, IS_ARRAY(this))) {
- var intervals = %GetArrayKeys(this, length);
- if (intervals.length == 2 && intervals[0] < 0) {
- // A single interval.
- var intervalMin = -(intervals[0] + 1);
- var intervalMax = intervalMin + intervals[1];
- if (min < intervalMin) min = intervalMin;
- max = intervalMax; // Capped by length already.
+ var indices = %GetArrayKeys(this, length);
+ if (IS_NUMBER(indices)) {
+ // It's an interval.
+ max = indices; // Capped by length already.
// Fall through to loop below.
} else {
- if (intervals.length == 0) return -1;
+ if (indices.length == 0) return -1;
// Get all the keys in sorted order.
- var sortedKeys = GetSortedArrayKeys(this, intervals);
+ var sortedKeys = GetSortedArrayKeys(this, indices);
var n = sortedKeys.length;
var i = 0;
while (i < n && sortedKeys[i] < index) i++;
@@ -1345,18 +1306,15 @@ function ArrayLastIndexOf(element, index) {
var min = 0;
var max = index;
if (UseSparseVariant(this, length, IS_ARRAY(this))) {
- var intervals = %GetArrayKeys(this, index + 1);
- if (intervals.length == 2 && intervals[0] < 0) {
- // A single interval.
- var intervalMin = -(intervals[0] + 1);
- var intervalMax = intervalMin + intervals[1];
- if (min < intervalMin) min = intervalMin;
- max = intervalMax; // Capped by index already.
+ var indices = %GetArrayKeys(this, index + 1);
+ if (IS_NUMBER(indices)) {
+ // It's an interval.
+ max = indices; // Capped by index already.
// Fall through to loop below.
} else {
- if (intervals.length == 0) return -1;
+ if (indices.length == 0) return -1;
// Get all the keys in sorted order.
- var sortedKeys = GetSortedArrayKeys(this, intervals);
+ var sortedKeys = GetSortedArrayKeys(this, indices);
var i = sortedKeys.length - 1;
while (i >= 0) {
var key = sortedKeys[i];
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
index 8536ca006..deef28b1f 100644
--- a/deps/v8/src/assembler.cc
+++ b/deps/v8/src/assembler.cc
@@ -927,20 +927,9 @@ void ExternalReference::InitializeMathExpData() {
math_exp_log_table_array = new double[kTableSize];
for (int i = 0; i < kTableSize; i++) {
double value = pow(2, i / kTableSizeDouble);
-
uint64_t bits = BitCast<uint64_t, double>(value);
bits &= (static_cast<uint64_t>(1) << 52) - 1;
double mantissa = BitCast<double, uint64_t>(bits);
-
- // <just testing>
- uint64_t doublebits;
- memcpy(&doublebits, &value, sizeof doublebits);
- doublebits &= (static_cast<uint64_t>(1) << 52) - 1;
- double mantissa2;
- memcpy(&mantissa2, &doublebits, sizeof mantissa2);
- CHECK_EQ(mantissa, mantissa2);
- // </just testing>
-
math_exp_log_table_array[i] = mantissa;
}
diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc
index 712bfd1b9..7d7a5b247 100644
--- a/deps/v8/src/ast.cc
+++ b/deps/v8/src/ast.cc
@@ -128,7 +128,8 @@ Assignment::Assignment(Isolate* isolate,
pos_(pos),
binary_operation_(NULL),
assignment_id_(GetNextId(isolate)),
- is_monomorphic_(false) { }
+ is_monomorphic_(false),
+ store_mode_(STANDARD_STORE) { }
Token::Value Assignment::binary_op() const {
@@ -413,12 +414,9 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
receiver_types_.Clear();
if (key()->IsPropertyName()) {
- ArrayLengthStub array_stub(Code::LOAD_IC);
FunctionPrototypeStub proto_stub(Code::LOAD_IC);
StringLengthStub string_stub(Code::LOAD_IC, false);
- if (oracle->LoadIsStub(this, &array_stub)) {
- is_array_length_ = true;
- } else if (oracle->LoadIsStub(this, &string_stub)) {
+ if (oracle->LoadIsStub(this, &string_stub)) {
is_string_length_ = true;
} else if (oracle->LoadIsStub(this, &proto_stub)) {
is_function_prototype_ = true;
@@ -455,9 +453,11 @@ void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
} else if (is_monomorphic_) {
// Record receiver type for monomorphic keyed stores.
receiver_types_.Add(oracle->StoreMonomorphicReceiverType(id), zone);
+ store_mode_ = oracle->GetStoreMode(id);
} else if (oracle->StoreIsPolymorphic(id)) {
receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
+ store_mode_ = oracle->GetStoreMode(id);
}
}
@@ -475,6 +475,7 @@ void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle,
receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
}
+ store_mode_ = oracle->GetStoreMode(id);
}
@@ -1061,6 +1062,7 @@ DONT_OPTIMIZE_NODE(ModuleVariable)
DONT_OPTIMIZE_NODE(ModulePath)
DONT_OPTIMIZE_NODE(ModuleUrl)
DONT_OPTIMIZE_NODE(ModuleStatement)
+DONT_OPTIMIZE_NODE(Yield)
DONT_OPTIMIZE_NODE(WithStatement)
DONT_OPTIMIZE_NODE(TryCatchStatement)
DONT_OPTIMIZE_NODE(TryFinallyStatement)
diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h
index 5debc74eb..dddfc835f 100644
--- a/deps/v8/src/ast.h
+++ b/deps/v8/src/ast.h
@@ -102,6 +102,7 @@ namespace internal {
V(ObjectLiteral) \
V(ArrayLiteral) \
V(Assignment) \
+ V(Yield) \
V(Throw) \
V(Property) \
V(Call) \
@@ -119,6 +120,10 @@ namespace internal {
STATEMENT_NODE_LIST(V) \
EXPRESSION_NODE_LIST(V)
+#ifdef WIN32
+#undef Yield
+#endif
+
// Forward declarations
class AstConstructionVisitor;
template<class> class AstNodeFactory;
@@ -349,6 +354,10 @@ class Expression: public AstNode {
ASSERT(types != NULL && types->length() == 1);
return types->at(0);
}
+ virtual KeyedAccessStoreMode GetStoreMode() {
+ UNREACHABLE();
+ return STANDARD_STORE;
+ }
BailoutId id() const { return id_; }
TypeFeedbackId test_id() const { return test_id_; }
@@ -1481,7 +1490,9 @@ class Property: public Expression {
void RecordTypeFeedback(TypeFeedbackOracle* oracle, Zone* zone);
virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
- bool IsArrayLength() { return is_array_length_; }
+ virtual KeyedAccessStoreMode GetStoreMode() {
+ return STANDARD_STORE;
+ }
bool IsUninitialized() { return is_uninitialized_; }
TypeFeedbackId PropertyFeedbackId() { return reuse(id()); }
@@ -1497,7 +1508,6 @@ class Property: public Expression {
load_id_(GetNextId(isolate)),
is_monomorphic_(false),
is_uninitialized_(false),
- is_array_length_(false),
is_string_length_(false),
is_string_access_(false),
is_function_prototype_(false) { }
@@ -1511,7 +1521,6 @@ class Property: public Expression {
SmallMapList receiver_types_;
bool is_monomorphic_ : 1;
bool is_uninitialized_ : 1;
- bool is_array_length_ : 1;
bool is_string_length_ : 1;
bool is_string_access_ : 1;
bool is_function_prototype_ : 1;
@@ -1773,6 +1782,9 @@ class CountOperation: public Expression {
void RecordTypeFeedback(TypeFeedbackOracle* oracle, Zone* znoe);
virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
+ virtual KeyedAccessStoreMode GetStoreMode() {
+ return store_mode_;
+ }
BailoutId AssignmentId() const { return assignment_id_; }
@@ -1788,6 +1800,8 @@ class CountOperation: public Expression {
: Expression(isolate),
op_(op),
is_prefix_(is_prefix),
+ is_monomorphic_(false),
+ store_mode_(STANDARD_STORE),
expression_(expr),
pos_(pos),
assignment_id_(GetNextId(isolate)),
@@ -1795,8 +1809,9 @@ class CountOperation: public Expression {
private:
Token::Value op_;
- bool is_prefix_;
- bool is_monomorphic_;
+ bool is_prefix_ : 1;
+ bool is_monomorphic_ : 1;
+ KeyedAccessStoreMode store_mode_: 4;
Expression* expression_;
int pos_;
const BailoutId assignment_id_;
@@ -1909,6 +1924,9 @@ class Assignment: public Expression {
void RecordTypeFeedback(TypeFeedbackOracle* oracle, Zone* zone);
virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
+ virtual KeyedAccessStoreMode GetStoreMode() {
+ return store_mode_;
+ }
protected:
Assignment(Isolate* isolate,
@@ -1934,11 +1952,37 @@ class Assignment: public Expression {
BinaryOperation* binary_operation_;
const BailoutId assignment_id_;
- bool is_monomorphic_;
+ bool is_monomorphic_ : 1;
+ KeyedAccessStoreMode store_mode_ : 4;
SmallMapList receiver_types_;
};
+class Yield: public Expression {
+ public:
+ DECLARE_NODE_TYPE(Yield)
+
+ Expression* expression() const { return expression_; }
+ bool is_delegating_yield() const { return is_delegating_yield_; }
+ virtual int position() const { return pos_; }
+
+ protected:
+ Yield(Isolate* isolate,
+ Expression* expression,
+ bool is_delegating_yield,
+ int pos)
+ : Expression(isolate),
+ expression_(expression),
+ is_delegating_yield_(is_delegating_yield),
+ pos_(pos) { }
+
+ private:
+ Expression* expression_;
+ bool is_delegating_yield_;
+ int pos_;
+};
+
+
class Throw: public Expression {
public:
DECLARE_NODE_TYPE(Throw)
@@ -1979,6 +2023,11 @@ class FunctionLiteral: public Expression {
kNotParenthesized
};
+ enum IsGeneratorFlag {
+ kIsGenerator,
+ kNotGenerator
+ };
+
DECLARE_NODE_TYPE(FunctionLiteral)
Handle<String> name() const { return name_; }
@@ -2039,6 +2088,10 @@ class FunctionLiteral: public Expression {
bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized);
}
+ bool is_generator() {
+ return IsGenerator::decode(bitfield_) == kIsGenerator;
+ }
+
int ast_node_count() { return ast_properties_.node_count(); }
AstProperties::Flags* flags() { return ast_properties_.flags(); }
void set_ast_properties(AstProperties* ast_properties) {
@@ -2059,7 +2112,8 @@ class FunctionLiteral: public Expression {
Type type,
ParameterFlag has_duplicate_parameters,
IsFunctionFlag is_function,
- IsParenthesizedFlag is_parenthesized)
+ IsParenthesizedFlag is_parenthesized,
+ IsGeneratorFlag is_generator)
: Expression(isolate),
name_(name),
scope_(scope),
@@ -2079,7 +2133,8 @@ class FunctionLiteral: public Expression {
Pretenure::encode(false) |
HasDuplicateParameters::encode(has_duplicate_parameters) |
IsFunction::encode(is_function) |
- IsParenthesized::encode(is_parenthesized);
+ IsParenthesized::encode(is_parenthesized) |
+ IsGenerator::encode(is_generator);
}
private:
@@ -2104,6 +2159,7 @@ class FunctionLiteral: public Expression {
class HasDuplicateParameters: public BitField<ParameterFlag, 4, 1> {};
class IsFunction: public BitField<IsFunctionFlag, 5, 1> {};
class IsParenthesized: public BitField<IsParenthesizedFlag, 6, 1> {};
+ class IsGenerator: public BitField<IsGeneratorFlag, 7, 1> {};
};
@@ -2902,6 +2958,12 @@ class AstNodeFactory BASE_EMBEDDED {
VISIT_AND_RETURN(Assignment, assign)
}
+ Yield* NewYield(Expression* expression, bool is_delegating_yield, int pos) {
+ Yield* yield =
+ new(zone_) Yield(isolate_, expression, is_delegating_yield, pos);
+ VISIT_AND_RETURN(Yield, yield)
+ }
+
Throw* NewThrow(Expression* exception, int pos) {
Throw* t = new(zone_) Throw(isolate_, exception, pos);
VISIT_AND_RETURN(Throw, t)
@@ -2920,13 +2982,14 @@ class AstNodeFactory BASE_EMBEDDED {
FunctionLiteral::ParameterFlag has_duplicate_parameters,
FunctionLiteral::Type type,
FunctionLiteral::IsFunctionFlag is_function,
- FunctionLiteral::IsParenthesizedFlag is_parenthesized) {
+ FunctionLiteral::IsParenthesizedFlag is_parenthesized,
+ FunctionLiteral::IsGeneratorFlag is_generator) {
FunctionLiteral* lit = new(zone_) FunctionLiteral(
isolate_, name, scope, body,
materialized_literal_count, expected_property_count, handler_count,
has_only_simple_this_property_assignments, this_property_assignments,
parameter_count, type, has_duplicate_parameters, is_function,
- is_parenthesized);
+ is_parenthesized, is_generator);
// Top-level literal doesn't count for the AST's properties.
if (is_function == FunctionLiteral::kIsFunction) {
visitor_.VisitFunctionLiteral(lit);
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc
index 58b2ad038..f57a1f6fd 100644
--- a/deps/v8/src/bootstrapper.cc
+++ b/deps/v8/src/bootstrapper.cc
@@ -303,9 +303,9 @@ Handle<Context> Bootstrapper::CreateEnvironment(
v8::ExtensionConfiguration* extensions) {
HandleScope scope(isolate_);
Genesis genesis(isolate_, global_object, global_template, extensions);
- Handle<Object> context(isolate_->global_handles()->Create(*genesis.result()));
- Handle<Context> env = Handle<Context>::cast(context);
- if (!env.is_null()) {
+ if (!genesis.result().is_null()) {
+ Handle<Object> ctx(isolate_->global_handles()->Create(*genesis.result()));
+ Handle<Context> env = Handle<Context>::cast(ctx);
if (InstallExtensions(env, extensions)) {
return env;
}
@@ -1280,7 +1280,17 @@ void Genesis::InitializeExperimentalGlobal() {
Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
// TODO(mstarzinger): Move this into Genesis::InitializeGlobal once we no
- // longer need to live behind a flag, so functions get added to the snapshot.
+ // longer need to live behind flags, so functions get added to the snapshot.
+
+ if (FLAG_harmony_symbols) {
+ // --- S y m b o l ---
+ Handle<JSFunction> symbol_fun =
+ InstallFunction(global, "Symbol", JS_VALUE_TYPE, JSValue::kSize,
+ isolate()->initial_object_prototype(),
+ Builtins::kIllegal, true);
+ native_context()->set_symbol_function(*symbol_fun);
+ }
+
if (FLAG_harmony_collections) {
{ // -- S e t
Handle<JSObject> prototype =
@@ -1301,6 +1311,16 @@ void Genesis::InitializeExperimentalGlobal() {
prototype, Builtins::kIllegal, true);
}
}
+
+ if (FLAG_harmony_typed_arrays) {
+ { // -- A r r a y B u f f e r
+ Handle<JSObject> prototype =
+ factory()->NewJSObject(isolate()->object_function(), TENURED);
+ InstallFunction(global, "__ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
+ JSArrayBuffer::kSize, prototype,
+ Builtins::kIllegal, true);
+ }
+ }
}
@@ -1436,9 +1456,6 @@ void Genesis::InstallNativeFunctions() {
}
void Genesis::InstallExperimentalNativeFunctions() {
- if (FLAG_harmony_symbols) {
- INSTALL_NATIVE(JSObject, "SymbolDelegate", symbol_delegate);
- }
if (FLAG_harmony_proxies) {
INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap);
INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap);
@@ -1911,6 +1928,11 @@ bool Genesis::InstallExperimentalNatives() {
"native object-observe.js") == 0) {
if (!CompileExperimentalBuiltin(isolate(), i)) return false;
}
+ if (FLAG_harmony_typed_arrays &&
+ strcmp(ExperimentalNatives::GetScriptName(i).start(),
+ "native typedarray.js") == 0) {
+ if (!CompileExperimentalBuiltin(isolate(), i)) return false;
+ }
}
InstallExperimentalNativeFunctions();
diff --git a/deps/v8/src/code-stubs-hydrogen.cc b/deps/v8/src/code-stubs-hydrogen.cc
index ae198bc24..ee903aef1 100644
--- a/deps/v8/src/code-stubs-hydrogen.cc
+++ b/deps/v8/src/code-stubs-hydrogen.cc
@@ -106,7 +106,8 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
Zone* zone = this->zone();
int param_count = descriptor_->register_param_count_;
HEnvironment* start_environment = graph()->start_environment();
- HBasicBlock* next_block = CreateBasicBlock(start_environment);
+ HBasicBlock* next_block =
+ CreateBasicBlock(start_environment, BailoutId::StubEntry());
current_block()->Goto(next_block);
next_block->SetJoinId(BailoutId::StubEntry());
set_current_block(next_block);
@@ -128,7 +129,8 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
if (descriptor_->stack_parameter_count_ != NULL) {
ASSERT(descriptor_->environment_length() == (param_count + 1));
stack_parameter_count = new(zone) HParameter(param_count,
- HParameter::REGISTER_PARAMETER);
+ HParameter::REGISTER_PARAMETER,
+ Representation::Integer32());
// it's essential to bind this value to the environment in case of deopt
start_environment->Bind(param_count, stack_parameter_count);
AddInstruction(stack_parameter_count);
@@ -146,13 +148,26 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
AddSimulate(BailoutId::StubEntry());
HValue* return_value = BuildCodeStub();
+
+ // We might have extra expressions to pop from the stack in addition to the
+ // arguments above
+ HInstruction* stack_pop_count = stack_parameter_count;
+ if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
+ HInstruction* amount = graph()->GetConstant1();
+ stack_pop_count = AddInstruction(
+ HAdd::New(zone, context_, stack_parameter_count, amount));
+ stack_pop_count->ChangeRepresentation(Representation::Integer32());
+ stack_pop_count->ClearFlag(HValue::kCanOverflow);
+ }
+
HReturn* hreturn_instruction = new(zone) HReturn(return_value,
context_,
- stack_parameter_count);
+ stack_pop_count);
current_block()->Finish(hreturn_instruction);
return true;
}
+
template <class Stub>
class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
public:
@@ -165,6 +180,14 @@ class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
};
+template <class Stub>
+static Handle<Code> DoGenerateCode(Stub* stub) {
+ CodeStubGraphBuilder<Stub> builder(stub);
+ LChunk* chunk = OptimizeGraph(builder.CreateGraph());
+ return chunk->Codegen(Code::COMPILED_STUB);
+}
+
+
template <>
HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
Zone* zone = this->zone();
@@ -176,7 +199,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
NULL,
FAST_ELEMENTS));
- CheckBuilder builder(this, BailoutId::StubEntry());
+ CheckBuilder builder(this);
builder.CheckNotUndefined(boilerplate);
int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize;
@@ -216,9 +239,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
- CodeStubGraphBuilder<FastCloneShallowObjectStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen(Code::COMPILED_STUB);
+ return DoGenerateCode(this);
}
@@ -227,16 +248,30 @@ HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
HInstruction* load = BuildUncheckedMonomorphicElementAccess(
GetParameter(0), GetParameter(1), NULL, NULL,
casted_stub()->is_js_array(), casted_stub()->elements_kind(),
- false, Representation::Tagged());
- AddInstruction(load);
+ false, STANDARD_STORE, Representation::Tagged());
return load;
}
Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
- CodeStubGraphBuilder<KeyedLoadFastElementStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen(Code::COMPILED_STUB);
+ return DoGenerateCode(this);
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
+ BuildUncheckedMonomorphicElementAccess(
+ GetParameter(0), GetParameter(1), GetParameter(2), NULL,
+ casted_stub()->is_js_array(), casted_stub()->elements_kind(),
+ true, casted_stub()->store_mode(), Representation::Tagged());
+ AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE);
+
+ return GetParameter(2);
+}
+
+
+Handle<Code> KeyedStoreFastElementStub::GenerateCode() {
+ return DoGenerateCode(this);
}
@@ -252,31 +287,19 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
AddInstruction(new(zone) HTrapAllocationMemento(js_array));
HInstruction* array_length =
- AddInstruction(new(zone) HJSArrayLength(js_array,
- js_array,
- HType::Smi()));
+ AddInstruction(HLoadNamedField::NewArrayLength(
+ zone, js_array, js_array, HType::Smi()));
- Heap* heap = isolate()->heap();
- const int kMinFreeNewSpaceAfterGC =
- ((heap->InitialSemiSpaceSize() - sizeof(FixedArrayBase)) / 2) /
- kDoubleSize;
-
- HConstant* max_alloc_size =
- new(zone) HConstant(kMinFreeNewSpaceAfterGC, Representation::Integer32());
- AddInstruction(max_alloc_size);
- // Since we're forcing Integer32 representation for this HBoundsCheck,
- // there's no need to Smi-check the index.
- AddInstruction(
- new(zone) HBoundsCheck(array_length, max_alloc_size,
- DONT_ALLOW_SMI_KEY, Representation::Integer32()));
+ ElementsKind to_kind = casted_stub()->to_kind();
+ BuildNewSpaceArrayCheck(array_length, to_kind);
- IfBuilder if_builder(this, BailoutId::StubEntry());
+ IfBuilder if_builder(this);
- if_builder.BeginTrue(array_length, graph()->GetConstant0(), Token::EQ);
+ if_builder.BeginIf(array_length, graph()->GetConstant0(), Token::EQ);
// Nothing to do, just change the map.
- if_builder.BeginFalse();
+ if_builder.BeginElse();
HInstruction* elements =
AddInstruction(new(zone) HLoadElements(js_array, js_array));
@@ -284,37 +307,14 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
HInstruction* elements_length =
AddInstruction(new(zone) HFixedArrayBaseLength(elements));
- ElementsKind to_kind = casted_stub()->to_kind();
HValue* new_elements =
BuildAllocateElements(context(), to_kind, elements_length);
- // Fast elements kinds need to be initialized in case statements below cause a
- // garbage collection.
- Factory* factory = isolate()->factory();
-
- ASSERT(!IsFastSmiElementsKind(to_kind));
- double nan_double = FixedDoubleArray::hole_nan_as_double();
- HValue* hole = IsFastObjectElementsKind(to_kind)
- ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
- Representation::Tagged()))
- : AddInstruction(new(zone) HConstant(nan_double,
- Representation::Double()));
-
- LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement,
- BailoutId::StubEntry());
-
- HValue* zero = graph()->GetConstant0();
- HValue* start = IsFastElementsKind(to_kind) ? zero : array_length;
- HValue* key = builder.BeginBody(start, elements_length, Token::LT);
-
- AddInstruction(new(zone) HStoreKeyed(new_elements, key, hole, to_kind));
- AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE);
-
- builder.EndBody();
-
BuildCopyElements(context(), elements,
casted_stub()->from_kind(), new_elements,
- to_kind, array_length);
+ to_kind, array_length, elements_length);
+
+ Factory* factory = isolate()->factory();
AddInstruction(new(zone) HStoreNamedField(js_array,
factory->elements_field_string(),
@@ -331,6 +331,11 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
}
+Handle<Code> TransitionElementsKindStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
template <>
HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
HInstruction* deopt = new(zone()) HSoftDeoptimize();
@@ -341,9 +346,7 @@ HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
- CodeStubGraphBuilder<ArrayNoArgumentConstructorStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen(Code::COMPILED_STUB);
+ return DoGenerateCode(this);
}
@@ -357,17 +360,8 @@ HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
}
-Handle<Code> TransitionElementsKindStub::GenerateCode() {
- CodeStubGraphBuilder<TransitionElementsKindStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen(Code::COMPILED_STUB);
-}
-
-
Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
- CodeStubGraphBuilder<ArraySingleArgumentConstructorStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen(Code::COMPILED_STUB);
+ return DoGenerateCode(this);
}
@@ -381,9 +375,7 @@ HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
- CodeStubGraphBuilder<ArrayNArgumentsConstructorStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen(Code::COMPILED_STUB);
+ return DoGenerateCode(this);
}
} } // namespace v8::internal
diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc
index 95bc1e99c..eff0f7f1c 100644
--- a/deps/v8/src/code-stubs.cc
+++ b/deps/v8/src/code-stubs.cc
@@ -510,6 +510,7 @@ void ToBooleanStub::Types::Print(StringStream* stream) const {
if (Contains(SMI)) stream->Add("Smi");
if (Contains(SPEC_OBJECT)) stream->Add("SpecObject");
if (Contains(STRING)) stream->Add("String");
+ if (Contains(SYMBOL)) stream->Add("Symbol");
if (Contains(HEAP_NUMBER)) stream->Add("HeapNumber");
}
@@ -549,6 +550,9 @@ bool ToBooleanStub::Types::Record(Handle<Object> object) {
Add(STRING);
return !object->IsUndetectableObject() &&
String::cast(*object)->length() != 0;
+ } else if (object->IsSymbol()) {
+ Add(SYMBOL);
+ return true;
} else if (object->IsHeapNumber()) {
ASSERT(!object->IsUndetectableObject());
Add(HEAP_NUMBER);
@@ -565,6 +569,7 @@ bool ToBooleanStub::Types::Record(Handle<Object> object) {
bool ToBooleanStub::Types::NeedsMap() const {
return Contains(ToBooleanStub::SPEC_OBJECT)
|| Contains(ToBooleanStub::STRING)
+ || Contains(ToBooleanStub::SYMBOL)
|| Contains(ToBooleanStub::HEAP_NUMBER);
}
@@ -614,10 +619,8 @@ void ElementsTransitionAndStoreStub::Generate(MacroAssembler* masm) {
void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
- int i = 0;
- for (; i <= StubFailureTrampolineStub::kMaxExtraExpressionStackCount; ++i) {
- StubFailureTrampolineStub(i).GetCode(isolate);
- }
+ StubFailureTrampolineStub(NOT_JS_FUNCTION_STUB_MODE).GetCode(isolate);
+ StubFailureTrampolineStub(JS_FUNCTION_STUB_MODE).GetCode(isolate);
}
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
index e91b24157..99ff5154e 100644
--- a/deps/v8/src/code-stubs.h
+++ b/deps/v8/src/code-stubs.h
@@ -47,7 +47,6 @@ namespace internal {
V(Compare) \
V(CompareIC) \
V(MathPow) \
- V(ArrayLength) \
V(StringLength) \
V(FunctionPrototype) \
V(StoreArrayLength) \
@@ -259,15 +258,17 @@ class PlatformCodeStub : public CodeStub {
};
+enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
+
struct CodeStubInterfaceDescriptor {
CodeStubInterfaceDescriptor()
: register_param_count_(-1),
stack_parameter_count_(NULL),
- extra_expression_stack_count_(0),
+ function_mode_(NOT_JS_FUNCTION_STUB_MODE),
register_params_(NULL) { }
int register_param_count_;
const Register* stack_parameter_count_;
- int extra_expression_stack_count_;
+ StubFunctionMode function_mode_;
Register* register_params_;
Address deoptimization_handler_;
@@ -597,16 +598,6 @@ class ICStub: public PlatformCodeStub {
};
-class ArrayLengthStub: public ICStub {
- public:
- explicit ArrayLengthStub(Code::Kind kind) : ICStub(kind) { }
- virtual void Generate(MacroAssembler* masm);
-
- private:
- virtual CodeStub::Major MajorKey() { return ArrayLength; }
-};
-
-
class FunctionPrototypeStub: public ICStub {
public:
explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
@@ -1312,6 +1303,47 @@ class KeyedLoadFastElementStub : public HydrogenCodeStub {
};
+class KeyedStoreFastElementStub : public HydrogenCodeStub {
+ public:
+ KeyedStoreFastElementStub(bool is_js_array,
+ ElementsKind elements_kind,
+ KeyedAccessStoreMode mode) {
+ bit_field_ = ElementsKindBits::encode(elements_kind) |
+ IsJSArrayBits::encode(is_js_array) |
+ StoreModeBits::encode(mode);
+ }
+
+ Major MajorKey() { return KeyedStoreElement; }
+ int MinorKey() { return bit_field_; }
+
+ bool is_js_array() const {
+ return IsJSArrayBits::decode(bit_field_);
+ }
+
+ ElementsKind elements_kind() const {
+ return ElementsKindBits::decode(bit_field_);
+ }
+
+ KeyedAccessStoreMode store_mode() const {
+ return StoreModeBits::decode(bit_field_);
+ }
+
+ virtual Handle<Code> GenerateCode();
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ private:
+ class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
+ class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
+ class IsJSArrayBits: public BitField<bool, 12, 1> {};
+ uint32_t bit_field_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
+};
+
+
class TransitionElementsKindStub : public HydrogenCodeStub {
public:
TransitionElementsKindStub(ElementsKind from_kind,
@@ -1447,6 +1479,7 @@ class ToBooleanStub: public PlatformCodeStub {
SMI,
SPEC_OBJECT,
STRING,
+ SYMBOL,
HEAP_NUMBER,
NUMBER_OF_TYPES
};
@@ -1570,10 +1603,8 @@ class StoreArrayLiteralElementStub : public PlatformCodeStub {
class StubFailureTrampolineStub : public PlatformCodeStub {
public:
- static const int kMaxExtraExpressionStackCount = 1;
-
- explicit StubFailureTrampolineStub(int extra_expression_stack_count)
- : extra_expression_stack_count_(extra_expression_stack_count) {}
+ explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
+ : function_mode_(function_mode) {}
virtual bool IsPregenerated() { return true; }
@@ -1581,11 +1612,11 @@ class StubFailureTrampolineStub : public PlatformCodeStub {
private:
Major MajorKey() { return StubFailureTrampoline; }
- int MinorKey() { return extra_expression_stack_count_; }
+ int MinorKey() { return static_cast<int>(function_mode_); }
void Generate(MacroAssembler* masm);
- int extra_expression_stack_count_;
+ StubFunctionMode function_mode_;
DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
};
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index 2c4dae5d4..6f9b901d9 100644
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -1121,6 +1121,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
+ function_info->set_is_generator(lit->is_generator());
}
diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h
index cd7ed6adc..a0ba2f7eb 100644
--- a/deps/v8/src/contexts.h
+++ b/deps/v8/src/contexts.h
@@ -103,6 +103,7 @@ enum BindingFlags {
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
+ V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
@@ -156,7 +157,6 @@ enum BindingFlags {
V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
error_message_for_code_gen_from_strings) \
- V(SYMBOL_DELEGATE_INDEX, JSObject, symbol_delegate) \
V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
to_complete_property_descriptor) \
V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
@@ -251,6 +251,7 @@ class Context: public FixedArray {
NUMBER_FUNCTION_INDEX,
STRING_FUNCTION_INDEX,
STRING_FUNCTION_PROTOTYPE_MAP_INDEX,
+ SYMBOL_FUNCTION_INDEX,
OBJECT_FUNCTION_INDEX,
INTERNAL_ARRAY_FUNCTION_INDEX,
ARRAY_FUNCTION_INDEX,
@@ -287,7 +288,6 @@ class Context: public FixedArray {
EMBEDDER_DATA_INDEX,
ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
- SYMBOL_DELEGATE_INDEX,
TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
DERIVED_HAS_TRAP_INDEX,
DERIVED_GET_TRAP_INDEX,
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc
index 805a0cf1a..b57e3907c 100644
--- a/deps/v8/src/d8.cc
+++ b/deps/v8/src/d8.cc
@@ -227,11 +227,13 @@ bool Shell::ExecuteString(Isolate* isolate,
}
#if !defined(V8_SHARED)
} else {
+ v8::TryCatch try_catch;
Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global();
Handle<Value> fun = global->Get(String::New("Stringify"));
Handle<Value> argv[1] = { result };
Handle<Value> s = Handle<Function>::Cast(fun)->Call(global, 1, argv);
+ if (try_catch.HasCaught()) return true;
v8::String::Utf8Value str(s);
fwrite(*str, sizeof(**str), str.length(), stdout);
printf("\n");
@@ -905,12 +907,6 @@ Handle<Value> Shell::Uint8ClampedArray(const Arguments& args) {
}
-Handle<Value> Shell::Yield(const Arguments& args) {
- v8::Unlocker unlocker(args.GetIsolate());
- return Undefined(args.GetIsolate());
-}
-
-
Handle<Value> Shell::Quit(const Arguments& args) {
int exit_code = args[0]->Int32Value();
OnExit();
diff --git a/deps/v8/src/d8.h b/deps/v8/src/d8.h
index 621ac7409..2789c0763 100644
--- a/deps/v8/src/d8.h
+++ b/deps/v8/src/d8.h
@@ -298,13 +298,8 @@ class Shell : public i::AllStatic {
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED
-#ifdef WIN32
-#undef Yield
-#endif
-
static Handle<Value> Print(const Arguments& args);
static Handle<Value> Write(const Arguments& args);
- static Handle<Value> Yield(const Arguments& args);
static Handle<Value> Quit(const Arguments& args);
static Handle<Value> Version(const Arguments& args);
static Handle<Value> EnableProfiler(const Arguments& args);
diff --git a/deps/v8/src/d8.js b/deps/v8/src/d8.js
index 1ff0ce898..df1046133 100644
--- a/deps/v8/src/d8.js
+++ b/deps/v8/src/d8.js
@@ -2214,7 +2214,8 @@ function Stringify(x, depth) {
return x.toString();
case "string":
return "\"" + x.toString() + "\"";
- // TODO(rossberg): add symbol case
+ case "symbol":
+ return "Symbol(" + (x.name ? Stringify(x.name, depth) : "") + ")"
case "object":
if (x === null) return "null";
if (x.constructor && x.constructor.name === "Array") {
diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc
index 7a876e71f..91af9ccc1 100644
--- a/deps/v8/src/debug.cc
+++ b/deps/v8/src/debug.cc
@@ -3761,8 +3761,8 @@ void LockingCommandMessageQueue::Clear() {
MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
: Thread("v8:MsgDispHelpr"),
- sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()),
- already_signalled_(false) {
+ isolate_(isolate), sem_(OS::CreateSemaphore(0)),
+ mutex_(OS::CreateMutex()), already_signalled_(false) {
}
@@ -3785,7 +3785,6 @@ void MessageDispatchHelperThread::Schedule() {
void MessageDispatchHelperThread::Run() {
- Isolate* isolate = Isolate::Current();
while (true) {
sem_->Wait();
{
@@ -3793,8 +3792,8 @@ void MessageDispatchHelperThread::Run() {
already_signalled_ = false;
}
{
- Locker locker(reinterpret_cast<v8::Isolate*>(isolate));
- isolate->debugger()->CallMessageDispatchHandler();
+ Locker locker(reinterpret_cast<v8::Isolate*>(isolate_));
+ isolate_->debugger()->CallMessageDispatchHandler();
}
}
}
diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h
index c7f06815b..459073fe0 100644
--- a/deps/v8/src/debug.h
+++ b/deps/v8/src/debug.h
@@ -1041,6 +1041,7 @@ class MessageDispatchHelperThread: public Thread {
private:
void Run();
+ Isolate* isolate_;
Semaphore* const sem_;
Mutex* const mutex_;
bool already_signalled_;
diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc
index f03025cbf..601faf723 100644
--- a/deps/v8/src/deoptimizer.cc
+++ b/deps/v8/src/deoptimizer.cc
@@ -1280,29 +1280,37 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
}
intptr_t caller_arg_count = 0;
- if (descriptor->stack_parameter_count_ != NULL) {
- caller_arg_count =
- input_->GetRegister(descriptor->stack_parameter_count_->code());
- }
+ bool arg_count_known = descriptor->stack_parameter_count_ == NULL;
// Build the Arguments object for the caller's parameters and a pointer to it.
output_frame_offset -= kPointerSize;
- value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
- (caller_arg_count - 1) * kPointerSize;
- output_frame->SetFrameSlot(output_frame_offset, value);
+ int args_arguments_offset = output_frame_offset;
+ intptr_t the_hole = reinterpret_cast<intptr_t>(
+ isolate_->heap()->the_hole_value());
+ if (arg_count_known) {
+ value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
+ (caller_arg_count - 1) * kPointerSize;
+ } else {
+ value = the_hole;
+ }
+
+ output_frame->SetFrameSlot(args_arguments_offset, value);
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
- V8PRIxPTR " ; args.arguments\n",
- top_address + output_frame_offset, output_frame_offset, value);
+ V8PRIxPTR " ; args.arguments %s\n",
+ top_address + args_arguments_offset, args_arguments_offset, value,
+ arg_count_known ? "" : "(the hole)");
}
output_frame_offset -= kPointerSize;
- value = caller_arg_count;
- output_frame->SetFrameSlot(output_frame_offset, value);
+ int length_frame_offset = output_frame_offset;
+ value = arg_count_known ? caller_arg_count : the_hole;
+ output_frame->SetFrameSlot(length_frame_offset, value);
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
- V8PRIxPTR " ; args.length\n",
- top_address + output_frame_offset, output_frame_offset, value);
+ V8PRIxPTR " ; args.length %s\n",
+ top_address + length_frame_offset, length_frame_offset, value,
+ arg_count_known ? "" : "(the hole)");
}
output_frame_offset -= kPointerSize;
@@ -1321,6 +1329,20 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
DoTranslateCommand(iterator, 0, output_frame_offset);
}
+ if (!arg_count_known) {
+ DoTranslateCommand(iterator, 0, length_frame_offset,
+ TRANSLATED_VALUE_IS_NATIVE);
+ caller_arg_count = output_frame->GetFrameSlot(length_frame_offset);
+ value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
+ (caller_arg_count - 1) * kPointerSize;
+ output_frame->SetFrameSlot(args_arguments_offset, value);
+ if (trace_) {
+ PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+ V8PRIxPTR " ; args.arguments\n",
+ top_address + args_arguments_offset, args_arguments_offset, value);
+ }
+ }
+
ASSERT(0 == output_frame_offset);
// Copy the double registers from the input into the output frame.
@@ -1331,8 +1353,9 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
// Compute this frame's PC, state, and continuation.
Code* trampoline = NULL;
- int extra = descriptor->extra_expression_stack_count_;
- StubFailureTrampolineStub(extra).FindCodeInCache(&trampoline, isolate_);
+ StubFunctionMode function_mode = descriptor->function_mode_;
+ StubFailureTrampolineStub(function_mode).FindCodeInCache(&trampoline,
+ isolate_);
ASSERT(trampoline != NULL);
output_frame->SetPc(reinterpret_cast<intptr_t>(
trampoline->instruction_start()));
@@ -1476,12 +1499,25 @@ void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
#endif
+static const char* TraceValueType(bool is_smi, bool is_native) {
+ if (is_native) {
+ return "native";
+ } else if (is_smi) {
+ return "smi";
+ }
+
+ return "heap number";
+}
+
+
void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
- int frame_index,
- unsigned output_offset) {
+ int frame_index,
+ unsigned output_offset,
+ DeoptimizerTranslatedValueType value_type) {
disasm::NameConverter converter;
// A GC-safe temporary placeholder that we can put in the output frame.
const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0));
+ bool is_native = value_type == TRANSLATED_VALUE_IS_NATIVE;
// Ignore commands marked as duplicate and act on the first non-duplicate.
Translation::Opcode opcode =
@@ -1524,7 +1560,9 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
case Translation::INT32_REGISTER: {
int input_reg = iterator->Next();
intptr_t value = input_->GetRegister(input_reg);
- bool is_smi = Smi::IsValid(value);
+ bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
+ Smi::IsValid(value);
+
if (trace_) {
PrintF(
" 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
@@ -1532,15 +1570,18 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
output_offset,
value,
converter.NameOfCPURegister(input_reg),
- is_smi ? "smi" : "heap number");
+ TraceValueType(is_smi, is_native));
}
if (is_smi) {
intptr_t tagged_value =
reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
+ } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
+ output_[frame_index]->SetFrameSlot(output_offset, value);
} else {
// We save the untagged value on the side and store a GC-safe
// temporary placeholder in the frame.
+ ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
static_cast<double>(static_cast<int32_t>(value)));
output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -1551,7 +1592,8 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
case Translation::UINT32_REGISTER: {
int input_reg = iterator->Next();
uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
- bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+ bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
+ (value <= static_cast<uintptr_t>(Smi::kMaxValue));
if (trace_) {
PrintF(
" 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIuPTR
@@ -1560,15 +1602,18 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
output_offset,
value,
converter.NameOfCPURegister(input_reg),
- is_smi ? "smi" : "heap number");
+ TraceValueType(is_smi, is_native));
}
if (is_smi) {
intptr_t tagged_value =
reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
+ } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
+ output_[frame_index]->SetFrameSlot(output_offset, value);
} else {
// We save the untagged value on the side and store a GC-safe
// temporary placeholder in the frame.
+ ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
static_cast<double>(static_cast<uint32_t>(value)));
output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -1617,7 +1662,8 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
unsigned input_offset =
input_->GetOffsetFromSlotIndex(input_slot_index);
intptr_t value = input_->GetFrameSlot(input_offset);
- bool is_smi = Smi::IsValid(value);
+ bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
+ Smi::IsValid(value);
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": ",
output_[frame_index]->GetTop() + output_offset);
@@ -1625,15 +1671,18 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
output_offset,
value,
input_offset,
- is_smi ? "smi" : "heap number");
+ TraceValueType(is_smi, is_native));
}
if (is_smi) {
intptr_t tagged_value =
reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
+ } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
+ output_[frame_index]->SetFrameSlot(output_offset, value);
} else {
// We save the untagged value on the side and store a GC-safe
// temporary placeholder in the frame.
+ ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
static_cast<double>(static_cast<int32_t>(value)));
output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -1647,7 +1696,8 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
input_->GetOffsetFromSlotIndex(input_slot_index);
uintptr_t value =
static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
- bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+ bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
+ (value <= static_cast<uintptr_t>(Smi::kMaxValue));
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": ",
output_[frame_index]->GetTop() + output_offset);
@@ -1655,15 +1705,18 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
output_offset,
value,
input_offset,
- is_smi ? "smi" : "heap number");
+ TraceValueType(is_smi, is_native));
}
if (is_smi) {
intptr_t tagged_value =
reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
+ } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
+ output_[frame_index]->SetFrameSlot(output_offset, value);
} else {
// We save the untagged value on the side and store a GC-safe
// temporary placeholder in the frame.
+ ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
static_cast<double>(static_cast<uint32_t>(value)));
output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -2130,7 +2183,8 @@ void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
ASSERT(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
desc.instr_size);
chunk->CommitArea(desc.instr_size);
- memcpy(chunk->area_start(), desc.buffer, desc.instr_size);
+ CopyBytes(chunk->area_start(), desc.buffer,
+ static_cast<size_t>(desc.instr_size));
CPU::FlushICache(chunk->area_start(), desc.instr_size);
if (type == EAGER) {
diff --git a/deps/v8/src/deoptimizer.h b/deps/v8/src/deoptimizer.h
index db0cc0bde..895ed6690 100644
--- a/deps/v8/src/deoptimizer.h
+++ b/deps/v8/src/deoptimizer.h
@@ -356,9 +356,17 @@ class Deoptimizer : public Malloced {
bool is_setter_stub_frame);
void DoComputeCompiledStubFrame(TranslationIterator* iterator,
int frame_index);
+
+ enum DeoptimizerTranslatedValueType {
+ TRANSLATED_VALUE_IS_NATIVE,
+ TRANSLATED_VALUE_IS_TAGGED
+ };
+
void DoTranslateCommand(TranslationIterator* iterator,
- int frame_index,
- unsigned output_offset);
+ int frame_index,
+ unsigned output_offset,
+ DeoptimizerTranslatedValueType value_type = TRANSLATED_VALUE_IS_TAGGED);
+
// Translate a command for OSR. Updates the input offset to be used for
// the next command. Returns false if translation of the command failed
// (e.g., a number conversion failed) and may or may not have updated the
diff --git a/deps/v8/src/elements-kind.h b/deps/v8/src/elements-kind.h
index cb3bb9c9e..da151924b 100644
--- a/deps/v8/src/elements-kind.h
+++ b/deps/v8/src/elements-kind.h
@@ -110,10 +110,15 @@ inline bool IsFastDoubleElementsKind(ElementsKind kind) {
}
+inline bool IsExternalFloatOrDoubleElementsKind(ElementsKind kind) {
+ return kind == EXTERNAL_DOUBLE_ELEMENTS ||
+ kind == EXTERNAL_FLOAT_ELEMENTS;
+}
+
+
inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
return IsFastDoubleElementsKind(kind) ||
- kind == EXTERNAL_DOUBLE_ELEMENTS ||
- kind == EXTERNAL_FLOAT_ELEMENTS;
+ IsExternalFloatOrDoubleElementsKind(kind);
}
diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h
index c4b560bc8..ea72168b7 100644
--- a/deps/v8/src/flag-definitions.h
+++ b/deps/v8/src/flag-definitions.h
@@ -148,6 +148,9 @@ DEFINE_bool(harmony_collections, false,
"enable harmony collections (sets, maps, and weak maps)")
DEFINE_bool(harmony_observation, false,
"enable harmony object observation (implies harmony collections")
+DEFINE_bool(harmony_typed_arrays, false,
+ "enable harmony typed arrays")
+DEFINE_bool(harmony_generators, false, "enable harmony generators")
DEFINE_bool(harmony, false, "enable all harmony features (except typeof)")
DEFINE_implication(harmony, harmony_scoping)
DEFINE_implication(harmony, harmony_modules)
@@ -155,14 +158,18 @@ DEFINE_implication(harmony, harmony_symbols)
DEFINE_implication(harmony, harmony_proxies)
DEFINE_implication(harmony, harmony_collections)
DEFINE_implication(harmony, harmony_observation)
+DEFINE_implication(harmony, harmony_generators)
DEFINE_implication(harmony_modules, harmony_scoping)
DEFINE_implication(harmony_observation, harmony_collections)
+DEFINE_implication(harmony, harmony_typed_arrays)
// Flags for experimental implementation features.
DEFINE_bool(packed_arrays, true, "optimizes arrays that have no holes")
DEFINE_bool(smi_only_arrays, true, "tracks arrays with only smi values")
DEFINE_bool(compiled_transitions, false, "use optimizing compiler to "
"generate array elements transition stubs")
+DEFINE_bool(compiled_keyed_stores, false, "use optimizing compiler to "
+ "generate keyed store stubs")
DEFINE_bool(clever_optimizations,
true,
"Optimize object size, Array shift, DOM strings and string +")
@@ -424,7 +431,7 @@ DEFINE_bool(trace_external_memory, false,
"it is adjusted.")
DEFINE_bool(collect_maps, true,
"garbage collect maps from which no objects can be reached")
-DEFINE_bool(weak_embedded_maps_in_optimized_code, true,
+DEFINE_bool(weak_embedded_maps_in_optimized_code, false,
"make maps embedded in optimized code weak")
DEFINE_bool(flush_code, true,
"flush code that we expect not to use again (during full gc)")
diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc
index ed407e796..aaf8c79e2 100644
--- a/deps/v8/src/frames.cc
+++ b/deps/v8/src/frames.cc
@@ -1311,18 +1311,19 @@ Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
Code* StubFailureTrampolineFrame::unchecked_code() const {
- int i = 0;
- for (; i <= StubFailureTrampolineStub::kMaxExtraExpressionStackCount; ++i) {
- Code* trampoline;
- StubFailureTrampolineStub(i).FindCodeInCache(&trampoline, isolate());
- ASSERT(trampoline != NULL);
- Address current_pc = pc();
- Address code_start = trampoline->instruction_start();
- Address code_end = code_start + trampoline->instruction_size();
- if (code_start <= current_pc && current_pc < code_end) {
- return trampoline;
- }
+ Code* trampoline;
+ StubFailureTrampolineStub(NOT_JS_FUNCTION_STUB_MODE).
+ FindCodeInCache(&trampoline, isolate());
+ if (trampoline->contains(pc())) {
+ return trampoline;
}
+
+ StubFailureTrampolineStub(JS_FUNCTION_STUB_MODE).
+ FindCodeInCache(&trampoline, isolate());
+ if (trampoline->contains(pc())) {
+ return trampoline;
+ }
+
UNREACHABLE();
return NULL;
}
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc
index cb6f228a1..1c6a0b91b 100644
--- a/deps/v8/src/full-codegen.cc
+++ b/deps/v8/src/full-codegen.cc
@@ -232,6 +232,12 @@ void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
}
+void BreakableStatementChecker::VisitYield(Yield* expr) {
+ // Yield is breakable if the expression is.
+ Visit(expr->expression());
+}
+
+
void BreakableStatementChecker::VisitThrow(Throw* expr) {
// Throw is breakable if the expression is.
Visit(expr->exception());
@@ -1538,6 +1544,28 @@ void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
}
+void FullCodeGenerator::VisitYield(Yield* expr) {
+ if (expr->is_delegating_yield())
+ UNIMPLEMENTED();
+
+ Comment cmnt(masm_, "[ Yield");
+ VisitForAccumulatorValue(expr->expression());
+ // TODO(wingo): Assert that the operand stack depth is 0, at least while
+ // general yield expressions are unimplemented.
+
+ // TODO(wingo): What follows is as in VisitReturnStatement. Replace it with a
+ // call to a builtin that will resume the generator.
+ NestedStatement* current = nesting_stack_;
+ int stack_depth = 0;
+ int context_length = 0;
+ while (current != NULL) {
+ current = current->Exit(&stack_depth, &context_length);
+ }
+ __ Drop(stack_depth);
+ EmitReturnSequence();
+}
+
+
void FullCodeGenerator::VisitThrow(Throw* expr) {
Comment cmnt(masm_, "[ Throw");
VisitForStackValue(expr->exception());
diff --git a/deps/v8/src/gdb-jit.cc b/deps/v8/src/gdb-jit.cc
index dde6bbdaa..cf8ca2d4d 100644
--- a/deps/v8/src/gdb-jit.cc
+++ b/deps/v8/src/gdb-jit.cc
@@ -187,7 +187,7 @@ class Writer BASE_EMBEDDED {
byte* buffer_;
};
-class StringTable;
+class ELFStringTable;
template<typename THeader>
class DebugSectionBase : public ZoneObject {
@@ -338,7 +338,7 @@ class ELFSection : public DebugSectionBase<ELFSectionHeader> {
virtual ~ELFSection() { }
- void PopulateHeader(Writer::Slot<Header> header, StringTable* strtab);
+ void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
uintptr_t start = w->position();
@@ -438,9 +438,9 @@ class FullHeaderELFSection : public ELFSection {
};
-class StringTable : public ELFSection {
+class ELFStringTable : public ELFSection {
public:
- explicit StringTable(const char* name)
+ explicit ELFStringTable(const char* name)
: ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) {
}
@@ -488,7 +488,7 @@ class StringTable : public ELFSection {
void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
- StringTable* strtab) {
+ ELFStringTable* strtab) {
header->name = strtab->Add(name_);
header->type = type_;
header->alignment = align_;
@@ -631,7 +631,7 @@ class ELF BASE_EMBEDDED {
public:
ELF(Zone* zone) : sections_(6, zone) {
sections_.Add(new(zone) ELFSection("", ELFSection::TYPE_NULL, 0), zone);
- sections_.Add(new(zone) StringTable(".shstrtab"), zone);
+ sections_.Add(new(zone) ELFStringTable(".shstrtab"), zone);
}
void Write(Writer* w) {
@@ -718,7 +718,7 @@ class ELF BASE_EMBEDDED {
w->CreateSlotsHere<ELFSection::Header>(sections_.length());
// String table for section table is the first section.
- StringTable* strtab = static_cast<StringTable*>(SectionAt(1));
+ ELFStringTable* strtab = static_cast<ELFStringTable*>(SectionAt(1));
strtab->AttachWriter(w);
for (int i = 0, length = sections_.length();
i < length;
@@ -832,7 +832,7 @@ class ELFSymbol BASE_EMBEDDED {
};
#endif
- void Write(Writer::Slot<SerializedLayout> s, StringTable* t) {
+ void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) {
// Convert symbol names from strings to indexes in the string table.
s->name = t->Add(name);
s->value = value;
@@ -871,8 +871,8 @@ class ELFSymbolTable : public ELFSection {
header->size = w->position() - header->offset;
// String table for this symbol table should follow it in the section table.
- StringTable* strtab =
- static_cast<StringTable*>(w->debug_object()->SectionAt(index() + 1));
+ ELFStringTable* strtab =
+ static_cast<ELFStringTable*>(w->debug_object()->SectionAt(index() + 1));
strtab->AttachWriter(w);
symbols.at(0).set(ELFSymbol::SerializedLayout(0,
0,
@@ -905,7 +905,7 @@ class ELFSymbolTable : public ELFSection {
private:
void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
Writer::Slot<ELFSymbol::SerializedLayout> dst,
- StringTable* strtab) {
+ ELFStringTable* strtab) {
for (int i = 0, len = src->length();
i < len;
i++) {
@@ -1023,7 +1023,7 @@ static void CreateSymbolsTable(CodeDescription* desc,
int text_section_index) {
Zone* zone = desc->info()->zone();
ELFSymbolTable* symtab = new(zone) ELFSymbolTable(".symtab", zone);
- StringTable* strtab = new(zone) StringTable(".strtab");
+ ELFStringTable* strtab = new(zone) ELFStringTable(".strtab");
// Symbol table should be followed by the linked string table.
elf->AddSection(symtab, zone);
@@ -1996,7 +1996,7 @@ static GDBJITLineInfo* UntagLineInfo(void* ptr) {
}
-void GDBJITInterface::AddCode(Handle<String> name,
+void GDBJITInterface::AddCode(Handle<Name> name,
Handle<Script> script,
Handle<Code> code,
CompilationInfo* info) {
@@ -2005,8 +2005,9 @@ void GDBJITInterface::AddCode(Handle<String> name,
// Force initialization of line_ends array.
GetScriptLineNumber(script, 0);
- if (!name.is_null()) {
- SmartArrayPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS);
+ if (!name.is_null() && name->IsString()) {
+ SmartArrayPointer<char> name_cstring =
+ Handle<String>::cast(name)->ToCString(DISALLOW_NULLS);
AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info);
} else {
AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
@@ -2124,10 +2125,14 @@ void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
- String* name,
+ Name* name,
Code* code) {
if (!FLAG_gdbjit) return;
- AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code);
+ if (name != NULL && name->IsString()) {
+ AddCode(tag, *String::cast(name)->ToCString(DISALLOW_NULLS), code);
+ } else {
+ AddCode(tag, "", code);
+ }
}
diff --git a/deps/v8/src/gdb-jit.h b/deps/v8/src/gdb-jit.h
index 0eca9384d..cc052c1c0 100644
--- a/deps/v8/src/gdb-jit.h
+++ b/deps/v8/src/gdb-jit.h
@@ -118,12 +118,12 @@ class GDBJITInterface: public AllStatic {
Script* script,
CompilationInfo* info);
- static void AddCode(Handle<String> name,
+ static void AddCode(Handle<Name> name,
Handle<Script> script,
Handle<Code> code,
CompilationInfo* info);
- static void AddCode(CodeTag tag, String* name, Code* code);
+ static void AddCode(CodeTag tag, Name* name, Code* code);
static void AddCode(CodeTag tag, const char* name, Code* code);
diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc
index 14c00f199..cb3115abf 100644
--- a/deps/v8/src/global-handles.cc
+++ b/deps/v8/src/global-handles.cc
@@ -72,7 +72,7 @@ class GlobalHandles::Node {
Internals::kNodeIsPartiallyDependentShift);
}
-#ifdef DEBUG
+#ifdef ENABLE_EXTRA_CHECKS
~Node() {
// TODO(1428): if it's a weak handle we should have invoked its callback.
// Zap the values for eager trapping.
@@ -111,10 +111,9 @@ class GlobalHandles::Node {
void Release(GlobalHandles* global_handles) {
ASSERT(state() != FREE);
set_state(FREE);
- // TODO(mstarzinger): Put behind debug flag once embedders are stabilized.
- object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
-#ifdef DEBUG
+#ifdef ENABLE_EXTRA_CHECKS
// Zap the values for eager trapping.
+ object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
set_independent(false);
set_partially_dependent(false);
diff --git a/deps/v8/src/handles-inl.h b/deps/v8/src/handles-inl.h
index fd60a350d..b763c86a7 100644
--- a/deps/v8/src/handles-inl.h
+++ b/deps/v8/src/handles-inl.h
@@ -107,7 +107,7 @@ void HandleScope::CloseScope() {
current->limit = prev_limit_;
DeleteExtensions(isolate_);
}
-#ifdef DEBUG
+#ifdef ENABLE_EXTRA_CHECKS
ZapRange(prev_next_, prev_limit_);
#endif
}
diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc
index 2958d2cc0..b24a4cd1d 100644
--- a/deps/v8/src/handles.cc
+++ b/deps/v8/src/handles.cc
@@ -101,12 +101,14 @@ void HandleScope::DeleteExtensions(Isolate* isolate) {
}
+#ifdef ENABLE_EXTRA_CHECKS
void HandleScope::ZapRange(Object** start, Object** end) {
ASSERT(end - start <= kHandleBlockSize);
for (Object** p = start; p != end; p++) {
*reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue;
}
}
+#endif
Address HandleScope::current_level_address(Isolate* isolate) {
@@ -259,20 +261,6 @@ Handle<Object> ForceDeleteProperty(Handle<JSObject> object,
}
-Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
- Handle<Name> key,
- Handle<Object> value,
- PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
- CALL_HEAP_FUNCTION(object->GetIsolate(),
- object->SetPropertyWithInterceptor(*key,
- *value,
- attributes,
- strict_mode),
- Object);
-}
-
-
Handle<Object> GetProperty(Handle<JSReceiver> obj,
const char* name) {
Isolate* isolate = obj->GetIsolate();
@@ -289,19 +277,6 @@ Handle<Object> GetProperty(Isolate* isolate,
}
-Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
- Handle<JSObject> holder,
- Handle<Name> name,
- PropertyAttributes* attributes) {
- Isolate* isolate = receiver->GetIsolate();
- CALL_HEAP_FUNCTION(isolate,
- holder->GetPropertyWithInterceptor(*receiver,
- *name,
- attributes),
- Object);
-}
-
-
Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) {
const bool skip_hidden_prototypes = false;
CALL_HEAP_FUNCTION(obj->GetIsolate(),
diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h
index 3e408b73f..c69713e44 100644
--- a/deps/v8/src/handles.h
+++ b/deps/v8/src/handles.h
@@ -160,13 +160,14 @@ class HandleScope {
// Extend the handle scope making room for more handles.
static internal::Object** Extend(Isolate* isolate);
+#ifdef ENABLE_EXTRA_CHECKS
// Zaps the handles in the half-open interval [start, end).
static void ZapRange(internal::Object** start, internal::Object** end);
+#endif
- friend class v8::internal::DeferredHandles;
friend class v8::HandleScope;
+ friend class v8::internal::DeferredHandles;
friend class v8::internal::HandleScopeImplementer;
- friend class v8::ImplementationUtilities;
friend class v8::internal::Isolate;
};
@@ -232,11 +233,6 @@ Handle<Object> GetProperty(Isolate* isolate,
Handle<Object> obj,
Handle<Object> key);
-Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
- Handle<JSObject> holder,
- Handle<String> name,
- PropertyAttributes* attributes);
-
Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value);
Handle<Object> LookupSingleCharacterStringFromCode(Isolate* isolate,
diff --git a/deps/v8/src/heap-inl.h b/deps/v8/src/heap-inl.h
index 9ed65d810..a15b8ef48 100644
--- a/deps/v8/src/heap-inl.h
+++ b/deps/v8/src/heap-inl.h
@@ -399,7 +399,9 @@ AllocationSpace Heap::TargetSpaceId(InstanceType type) {
ASSERT(type != ODDBALL_TYPE);
ASSERT(type != JS_GLOBAL_PROPERTY_CELL_TYPE);
- if (type < FIRST_NONSTRING_TYPE) {
+ if (type <= LAST_NAME_TYPE) {
+ if (type == SYMBOL_TYPE) return OLD_POINTER_SPACE;
+ ASSERT(type < FIRST_NONSTRING_TYPE);
// There are four string representations: sequential strings, external
// strings, cons strings, and sliced strings.
// Only the latter two contain non-map-word pointers to heap objects.
diff --git a/deps/v8/src/heap-profiler.cc b/deps/v8/src/heap-profiler.cc
index c9f1d501d..5c1badf9c 100644
--- a/deps/v8/src/heap-profiler.cc
+++ b/deps/v8/src/heap-profiler.cc
@@ -44,72 +44,13 @@ HeapProfiler::~HeapProfiler() {
}
-void HeapProfiler::ResetSnapshots() {
+void HeapProfiler::DeleteAllSnapshots() {
Heap* the_heap = heap();
delete snapshots_;
snapshots_ = new HeapSnapshotsCollection(the_heap);
}
-void HeapProfiler::SetUp() {
- Isolate* isolate = Isolate::Current();
- if (isolate->heap_profiler() == NULL) {
- isolate->set_heap_profiler(new HeapProfiler(isolate->heap()));
- }
-}
-
-
-void HeapProfiler::TearDown() {
- Isolate* isolate = Isolate::Current();
- delete isolate->heap_profiler();
- isolate->set_heap_profiler(NULL);
-}
-
-
-HeapSnapshot* HeapProfiler::TakeSnapshot(
- const char* name,
- int type,
- v8::ActivityControl* control,
- v8::HeapProfiler::ObjectNameResolver* resolver) {
- ASSERT(Isolate::Current()->heap_profiler() != NULL);
- return Isolate::Current()->heap_profiler()->TakeSnapshotImpl(name,
- type,
- control,
- resolver);
-}
-
-
-HeapSnapshot* HeapProfiler::TakeSnapshot(
- String* name,
- int type,
- v8::ActivityControl* control,
- v8::HeapProfiler::ObjectNameResolver* resolver) {
- ASSERT(Isolate::Current()->heap_profiler() != NULL);
- return Isolate::Current()->heap_profiler()->TakeSnapshotImpl(name,
- type,
- control,
- resolver);
-}
-
-
-void HeapProfiler::StartHeapObjectsTracking() {
- ASSERT(Isolate::Current()->heap_profiler() != NULL);
- Isolate::Current()->heap_profiler()->StartHeapObjectsTrackingImpl();
-}
-
-
-void HeapProfiler::StopHeapObjectsTracking() {
- ASSERT(Isolate::Current()->heap_profiler() != NULL);
- Isolate::Current()->heap_profiler()->StopHeapObjectsTrackingImpl();
-}
-
-
-SnapshotObjectId HeapProfiler::PushHeapObjectsStats(v8::OutputStream* stream) {
- ASSERT(Isolate::Current()->heap_profiler() != NULL);
- return Isolate::Current()->heap_profiler()->PushHeapObjectsStatsImpl(stream);
-}
-
-
void HeapProfiler::DefineWrapperClass(
uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback) {
ASSERT(class_id != v8::HeapProfiler::kPersistentHandleNoClassId);
@@ -129,99 +70,69 @@ v8::RetainedObjectInfo* HeapProfiler::ExecuteWrapperClassCallback(
}
-HeapSnapshot* HeapProfiler::TakeSnapshotImpl(
+HeapSnapshot* HeapProfiler::TakeSnapshot(
const char* name,
- int type,
v8::ActivityControl* control,
v8::HeapProfiler::ObjectNameResolver* resolver) {
- HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type);
- HeapSnapshot* result =
- snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++);
- bool generation_completed = true;
- switch (s_type) {
- case HeapSnapshot::kFull: {
- HeapSnapshotGenerator generator(result, control, resolver, heap());
- generation_completed = generator.GenerateSnapshot();
- break;
+ HeapSnapshot* result = snapshots_->NewSnapshot(name, next_snapshot_uid_++);
+ {
+ HeapSnapshotGenerator generator(result, control, resolver, heap());
+ if (!generator.GenerateSnapshot()) {
+ delete result;
+ result = NULL;
}
- default:
- UNREACHABLE();
- }
- if (!generation_completed) {
- delete result;
- result = NULL;
}
snapshots_->SnapshotGenerationFinished(result);
return result;
}
-HeapSnapshot* HeapProfiler::TakeSnapshotImpl(
+HeapSnapshot* HeapProfiler::TakeSnapshot(
String* name,
- int type,
v8::ActivityControl* control,
v8::HeapProfiler::ObjectNameResolver* resolver) {
- return TakeSnapshotImpl(snapshots_->names()->GetName(name), type, control,
- resolver);
+ return TakeSnapshot(snapshots_->names()->GetName(name), control, resolver);
}
-void HeapProfiler::StartHeapObjectsTrackingImpl() {
+void HeapProfiler::StartHeapObjectsTracking() {
snapshots_->StartHeapObjectsTracking();
}
-SnapshotObjectId HeapProfiler::PushHeapObjectsStatsImpl(OutputStream* stream) {
+SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream) {
return snapshots_->PushHeapObjectsStats(stream);
}
-void HeapProfiler::StopHeapObjectsTrackingImpl() {
+void HeapProfiler::StopHeapObjectsTracking() {
snapshots_->StopHeapObjectsTracking();
}
size_t HeapProfiler::GetMemorySizeUsedByProfiler() {
- HeapProfiler* profiler = Isolate::Current()->heap_profiler();
- ASSERT(profiler != NULL);
- size_t size = profiler->snapshots_->GetUsedMemorySize();
- return size;
+ return snapshots_->GetUsedMemorySize();
}
int HeapProfiler::GetSnapshotsCount() {
- HeapProfiler* profiler = Isolate::Current()->heap_profiler();
- ASSERT(profiler != NULL);
- return profiler->snapshots_->snapshots()->length();
+ return snapshots_->snapshots()->length();
}
HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
- HeapProfiler* profiler = Isolate::Current()->heap_profiler();
- ASSERT(profiler != NULL);
- return profiler->snapshots_->snapshots()->at(index);
+ return snapshots_->snapshots()->at(index);
}
HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
- HeapProfiler* profiler = Isolate::Current()->heap_profiler();
- ASSERT(profiler != NULL);
- return profiler->snapshots_->GetSnapshot(uid);
+ return snapshots_->GetSnapshot(uid);
}
SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
if (!obj->IsHeapObject())
return v8::HeapProfiler::kUnknownObjectId;
- HeapProfiler* profiler = Isolate::Current()->heap_profiler();
- ASSERT(profiler != NULL);
- return profiler->snapshots_->FindObjectId(HeapObject::cast(*obj)->address());
-}
-
-
-void HeapProfiler::DeleteAllSnapshots() {
- HeapProfiler* profiler = Isolate::Current()->heap_profiler();
- ASSERT(profiler != NULL);
- profiler->ResetSnapshots();
+ return snapshots_->FindObjectId(HeapObject::cast(*obj)->address());
}
diff --git a/deps/v8/src/heap-profiler.h b/deps/v8/src/heap-profiler.h
index c8c94f58d..3f3138db5 100644
--- a/deps/v8/src/heap-profiler.h
+++ b/deps/v8/src/heap-profiler.h
@@ -46,30 +46,28 @@ class HeapSnapshotsCollection;
class HeapProfiler {
public:
- static void SetUp();
- static void TearDown();
+ explicit HeapProfiler(Heap* heap);
+ ~HeapProfiler();
- static size_t GetMemorySizeUsedByProfiler();
+ size_t GetMemorySizeUsedByProfiler();
- static HeapSnapshot* TakeSnapshot(
+ HeapSnapshot* TakeSnapshot(
const char* name,
- int type,
v8::ActivityControl* control,
v8::HeapProfiler::ObjectNameResolver* resolver);
- static HeapSnapshot* TakeSnapshot(
+ HeapSnapshot* TakeSnapshot(
String* name,
- int type,
v8::ActivityControl* control,
v8::HeapProfiler::ObjectNameResolver* resolver);
- static void StartHeapObjectsTracking();
- static void StopHeapObjectsTracking();
- static SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
- static int GetSnapshotsCount();
- static HeapSnapshot* GetSnapshot(int index);
- static HeapSnapshot* FindSnapshot(unsigned uid);
- static SnapshotObjectId GetSnapshotObjectId(Handle<Object> obj);
- static void DeleteAllSnapshots();
+ void StartHeapObjectsTracking();
+ void StopHeapObjectsTracking();
+ SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
+ int GetSnapshotsCount();
+ HeapSnapshot* GetSnapshot(int index);
+ HeapSnapshot* FindSnapshot(unsigned uid);
+ SnapshotObjectId GetSnapshotObjectId(Handle<Object> obj);
+ void DeleteAllSnapshots();
void ObjectMoveEvent(Address from, Address to);
@@ -83,24 +81,6 @@ class HeapProfiler {
}
private:
- explicit HeapProfiler(Heap* heap);
- ~HeapProfiler();
- HeapSnapshot* TakeSnapshotImpl(
- const char* name,
- int type,
- v8::ActivityControl* control,
- v8::HeapProfiler::ObjectNameResolver* resolver);
- HeapSnapshot* TakeSnapshotImpl(
- String* name,
- int type,
- v8::ActivityControl* control,
- v8::HeapProfiler::ObjectNameResolver* resolver);
- void ResetSnapshots();
-
- void StartHeapObjectsTrackingImpl();
- void StopHeapObjectsTrackingImpl();
- SnapshotObjectId PushHeapObjectsStatsImpl(OutputStream* stream);
-
Heap* heap() const { return snapshots_->heap(); }
HeapSnapshotsCollection* snapshots_;
diff --git a/deps/v8/src/heap-snapshot-generator-inl.h b/deps/v8/src/heap-snapshot-generator-inl.h
index 43002d2d2..1a878c6df 100644
--- a/deps/v8/src/heap-snapshot-generator-inl.h
+++ b/deps/v8/src/heap-snapshot-generator-inl.h
@@ -85,3 +85,4 @@ int V8HeapExplorer::GetGcSubrootOrder(HeapObject* subroot) {
} } // namespace v8::internal
#endif // V8_HEAP_SNAPSHOT_GENERATOR_INL_H_
+
diff --git a/deps/v8/src/heap-snapshot-generator.cc b/deps/v8/src/heap-snapshot-generator.cc
index 824e50793..fb239aa3c 100644
--- a/deps/v8/src/heap-snapshot-generator.cc
+++ b/deps/v8/src/heap-snapshot-generator.cc
@@ -189,7 +189,7 @@ template <> struct SnapshotSizeConstants<4> {
static const int kExpectedHeapGraphEdgeSize = 12;
static const int kExpectedHeapEntrySize = 24;
static const int kExpectedHeapSnapshotsCollectionSize = 100;
- static const int kExpectedHeapSnapshotSize = 136;
+ static const int kExpectedHeapSnapshotSize = 132;
static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
};
@@ -197,7 +197,7 @@ template <> struct SnapshotSizeConstants<8> {
static const int kExpectedHeapGraphEdgeSize = 24;
static const int kExpectedHeapEntrySize = 32;
static const int kExpectedHeapSnapshotsCollectionSize = 152;
- static const int kExpectedHeapSnapshotSize = 168;
+ static const int kExpectedHeapSnapshotSize = 160;
static const uint64_t kMaxSerializableSnapshotRawSize =
static_cast<uint64_t>(6000) * MB;
};
@@ -205,11 +205,9 @@ template <> struct SnapshotSizeConstants<8> {
} // namespace
HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
- HeapSnapshot::Type type,
const char* title,
unsigned uid)
: collection_(collection),
- type_(type),
title_(title),
uid_(uid),
root_index_(HeapEntry::kNoEntry),
@@ -599,11 +597,10 @@ HeapSnapshotsCollection::~HeapSnapshotsCollection() {
}
-HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(HeapSnapshot::Type type,
- const char* name,
+HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name,
unsigned uid) {
is_tracking_objects_ = true; // Start watching for heap objects moves.
- return new HeapSnapshot(this, type, name, uid);
+ return new HeapSnapshot(this, name, uid);
}
@@ -2410,7 +2407,6 @@ void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
HeapSnapshot* result = new HeapSnapshot(snapshot_->collection(),
- HeapSnapshot::kFull,
snapshot_->title(),
snapshot_->uid());
result->AddRootEntry();
diff --git a/deps/v8/src/heap-snapshot-generator.h b/deps/v8/src/heap-snapshot-generator.h
index 7331b5f0b..a4fcef72b 100644
--- a/deps/v8/src/heap-snapshot-generator.h
+++ b/deps/v8/src/heap-snapshot-generator.h
@@ -157,18 +157,12 @@ class HeapSnapshotsCollection;
// HeapSnapshotGenerator fills in a HeapSnapshot.
class HeapSnapshot {
public:
- enum Type {
- kFull = v8::HeapSnapshot::kFull
- };
-
HeapSnapshot(HeapSnapshotsCollection* collection,
- Type type,
const char* title,
unsigned uid);
void Delete();
HeapSnapshotsCollection* collection() { return collection_; }
- Type type() { return type_; }
const char* title() { return title_; }
unsigned uid() { return uid_; }
size_t RawSnapshotSize() const;
@@ -203,7 +197,6 @@ class HeapSnapshot {
private:
HeapSnapshotsCollection* collection_;
- Type type_;
const char* title_;
unsigned uid_;
int root_index_;
@@ -305,8 +298,7 @@ class HeapSnapshotsCollection {
void StartHeapObjectsTracking() { is_tracking_objects_ = true; }
void StopHeapObjectsTracking() { ids_.StopHeapObjectsTracking(); }
- HeapSnapshot* NewSnapshot(
- HeapSnapshot::Type type, const char* name, unsigned uid);
+ HeapSnapshot* NewSnapshot(const char* name, unsigned uid);
void SnapshotGenerationFinished(HeapSnapshot* snapshot);
List<HeapSnapshot*>* snapshots() { return &snapshots_; }
HeapSnapshot* GetSnapshot(unsigned uid);
@@ -695,3 +687,4 @@ class HeapSnapshotJSONSerializer {
} } // namespace v8::internal
#endif // V8_HEAP_SNAPSHOT_GENERATOR_H_
+
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index 3cf23d036..fafcb64d3 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -1779,6 +1779,10 @@ class ScavengingVisitor : public StaticVisitorBase {
&ObjectEvacuationStrategy<POINTER_OBJECT>::
template VisitSpecialized<SlicedString::kSize>);
+ table_.Register(kVisitSymbol,
+ &ObjectEvacuationStrategy<POINTER_OBJECT>::
+ template VisitSpecialized<Symbol::kSize>);
+
table_.Register(kVisitSharedFunctionInfo,
&ObjectEvacuationStrategy<POINTER_OBJECT>::
template VisitSpecialized<SharedFunctionInfo::kSize>);
@@ -3785,11 +3789,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
ASSERT(!isolate_->code_range()->exists() ||
isolate_->code_range()->contains(code->address()));
code->set_instruction_size(desc.instr_size);
- // TODO(mstarzinger): Remove once we found the bug.
- CHECK(reloc_info->IsByteArray());
code->set_relocation_info(reloc_info);
- // TODO(mstarzinger): Remove once we found the bug.
- CHECK(code->relocation_info()->IsByteArray());
code->set_flags(flags);
if (code->is_call_stub() || code->is_keyed_call_stub()) {
code->set_check_type(RECEIVER_MAP_CHECK);
@@ -3805,8 +3805,6 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
}
// Allow self references to created code object by patching the handle to
// point to the newly allocated Code object.
- CHECK(code->IsCode());
- CHECK(code->relocation_info()->IsByteArray());
if (!self_reference.is_null()) {
*(self_reference.location()) = code;
}
@@ -3815,8 +3813,6 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
// that are dereferenced during the copy to point directly to the actual heap
// objects. These pointers can include references to the code object itself,
// through the self_reference parameter.
- CHECK(code->IsCode());
- CHECK(code->relocation_info()->IsByteArray());
code->CopyFrom(desc);
#ifdef VERIFY_HEAP
@@ -3888,13 +3884,15 @@ MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) {
Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
// Copy header and instructions.
- memcpy(new_addr, old_addr, relocation_offset);
+ CopyBytes(new_addr, old_addr, relocation_offset);
Code* new_code = Code::cast(result);
new_code->set_relocation_info(ByteArray::cast(reloc_info_array));
// Copy patched rinfo.
- memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length());
+ CopyBytes(new_code->relocation_start(),
+ reloc_info.start(),
+ static_cast<size_t>(reloc_info.length()));
// Relocate the copy.
ASSERT(!isolate_->code_range()->exists() ||
@@ -5430,13 +5428,13 @@ MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) {
}
-MaybeObject* Heap::AllocateSymbol(PretenureFlag pretenure) {
+MaybeObject* Heap::AllocateSymbol() {
// Statically ensure that it is safe to allocate symbols in paged spaces.
STATIC_ASSERT(Symbol::kSize <= Page::kNonCodeObjectAreaSize);
- AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
Object* result;
- MaybeObject* maybe = AllocateRaw(Symbol::kSize, space, OLD_DATA_SPACE);
+ MaybeObject* maybe =
+ AllocateRaw(Symbol::kSize, OLD_POINTER_SPACE, OLD_POINTER_SPACE);
if (!maybe->ToObject(&result)) return maybe;
HeapObject::cast(result)->set_map_no_write_barrier(symbol_map());
@@ -5452,6 +5450,7 @@ MaybeObject* Heap::AllocateSymbol(PretenureFlag pretenure) {
Symbol::cast(result)->set_hash_field(
Name::kIsNotArrayIndexMask | (hash << Name::kHashShift));
+ Symbol::cast(result)->set_name(undefined_value());
ASSERT(result->IsSymbol());
return result;
@@ -7471,6 +7470,9 @@ void KeyedLookupCache::Update(Map* map, Name* name, int field_offset) {
}
name = internalized_string;
}
+ // This cache is cleared only between mark compact passes, so we expect the
+ // cache to only contain old space names.
+ ASSERT(!HEAP->InNewSpace(name));
int index = (Hash(map, name) & kHashMask);
// After a GC there will be free slots, so we use them in order (this may
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h
index d26c38476..8992e318e 100644
--- a/deps/v8/src/heap.h
+++ b/deps/v8/src/heap.h
@@ -213,6 +213,8 @@ namespace internal {
V(prototype_string, "prototype") \
V(string_string, "string") \
V(String_string, "String") \
+ V(symbol_string, "symbol") \
+ V(Symbol_string, "Symbol") \
V(Date_string, "Date") \
V(this_string, "this") \
V(to_string_string, "toString") \
@@ -220,6 +222,7 @@ namespace internal {
V(undefined_string, "undefined") \
V(value_of_string, "valueOf") \
V(stack_string, "stack") \
+ V(toJSON_string, "toJSON") \
V(InitializeVarGlobal_string, "InitializeVarGlobal") \
V(InitializeConstGlobal_string, "InitializeConstGlobal") \
V(KeyedLoadElementMonomorphic_string, \
@@ -520,6 +523,7 @@ class Heap {
int InitialSemiSpaceSize() { return initial_semispace_size_; }
intptr_t MaxOldGenerationSize() { return max_old_generation_size_; }
intptr_t MaxExecutableSize() { return max_executable_size_; }
+ int MaxNewSpaceAllocationSize() { return InitialSemiSpaceSize() * 3/4; }
// Returns the capacity of the heap in bytes w/o growing. Heap grows when
// more spaces are needed until it reaches the limit.
@@ -878,12 +882,11 @@ class Heap {
void* external_pointer,
PretenureFlag pretenure);
- // Allocate a symbol.
+ // Allocate a symbol in old space.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
- MUST_USE_RESULT MaybeObject* AllocateSymbol(
- PretenureFlag pretenure = NOT_TENURED);
+ MUST_USE_RESULT MaybeObject* AllocateSymbol();
// Allocate a tenured JS global property cell.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc
index fc80748a6..edbffc2e2 100644
--- a/deps/v8/src/hydrogen-instructions.cc
+++ b/deps/v8/src/hydrogen-instructions.cc
@@ -1277,7 +1277,8 @@ Representation HBranch::observed_input_representation(int index) {
ToBooleanStub::UNDEFINED |
ToBooleanStub::NULL_TYPE |
ToBooleanStub::SPEC_OBJECT |
- ToBooleanStub::STRING);
+ ToBooleanStub::STRING |
+ ToBooleanStub::SYMBOL);
if (expected_input_types_.ContainsAnyOf(tagged_types)) {
return Representation::Tagged();
} else if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -1467,15 +1468,6 @@ void HChange::PrintDataTo(StringStream* stream) {
}
-void HJSArrayLength::PrintDataTo(StringStream* stream) {
- value()->PrintNameTo(stream);
- if (HasTypeCheck()) {
- stream->Add(" ");
- typecheck()->PrintNameTo(stream);
- }
-}
-
-
HValue* HUnaryMathOperation::Canonicalize() {
if (op() == kMathFloor) {
// If the input is integer32 then we replace the floor instruction
@@ -2415,6 +2407,10 @@ void HParameter::PrintDataTo(StringStream* stream) {
void HLoadNamedField::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
+ if (HasTypeCheck()) {
+ stream->Add(" ");
+ typecheck()->PrintNameTo(stream);
+ }
}
@@ -2589,6 +2585,10 @@ bool HLoadKeyed::UsesMustHandleHole() const {
return false;
}
+ if (IsExternalArrayElementsKind(elements_kind())) {
+ return false;
+ }
+
if (hole_mode() == ALLOW_RETURN_HOLE) return true;
if (IsFastDoubleElementsKind(elements_kind())) {
@@ -2611,6 +2611,10 @@ bool HLoadKeyed::RequiresHoleCheck() const {
return false;
}
+ if (IsExternalArrayElementsKind(elements_kind())) {
+ return false;
+ }
+
return !UsesMustHandleHole();
}
@@ -3036,10 +3040,19 @@ bool HStoreKeyed::NeedsCanonicalization() {
// If value is an integer or smi or comes from the result of a keyed load or
// constant then it is either be a non-hole value or in the case of a constant
// the hole is only being stored explicitly: no need for canonicalization.
- if (value()->IsLoadKeyed() || value()->IsConstant()) {
+ //
+ // The exception to that is keyed loads from external float or double arrays:
+ // these can load arbitrary representation of NaN.
+
+ if (value()->IsConstant()) {
return false;
}
+ if (value()->IsLoadKeyed()) {
+ return IsExternalFloatOrDoubleElementsKind(
+ HLoadKeyed::cast(value())->elements_kind());
+ }
+
if (value()->IsChange()) {
if (HChange::cast(value())->from().IsInteger32()) {
return false;
diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h
index f741f292e..ad0368718 100644
--- a/deps/v8/src/hydrogen-instructions.h
+++ b/deps/v8/src/hydrogen-instructions.h
@@ -134,7 +134,6 @@ class LChunkBuilder;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(LeaveInlined) \
V(LoadContextSlot) \
V(LoadElements) \
@@ -2392,45 +2391,6 @@ class HCallRuntime: public HCall<1> {
};
-class HJSArrayLength: public HTemplateInstruction<2> {
- public:
- HJSArrayLength(HValue* value, HValue* typecheck,
- HType type = HType::Tagged()) {
- set_type(type);
- // The length of an array is stored as a tagged value in the array
- // object. It is guaranteed to be 32 bit integer, but it can be
- // represented as either a smi or heap number.
- SetOperandAt(0, value);
- SetOperandAt(1, typecheck != NULL ? typecheck : value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnArrayLengths);
- SetGVNFlag(kDependsOnMaps);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* value() { return OperandAt(0); }
- HValue* typecheck() {
- ASSERT(HasTypeCheck());
- return OperandAt(1);
- }
- bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
-
- protected:
- virtual bool DataEquals(HValue* other_raw) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
class HFixedArrayBaseLength: public HUnaryOperation {
public:
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
@@ -4693,6 +4653,14 @@ class HParameter: public HTemplateInstruction<0> {
set_representation(Representation::Tagged());
}
+ explicit HParameter(unsigned index,
+ ParameterKind kind,
+ Representation r)
+ : index_(index),
+ kind_(kind) {
+ set_representation(r);
+ }
+
unsigned index() const { return index_; }
ParameterKind kind() const { return kind_; }
@@ -5184,12 +5152,16 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
};
-class HLoadNamedField: public HUnaryOperation {
+class HLoadNamedField: public HTemplateInstruction<2> {
public:
- HLoadNamedField(HValue* object, bool is_in_object, int offset)
- : HUnaryOperation(object),
- is_in_object_(is_in_object),
+ HLoadNamedField(HValue* object, bool is_in_object, int offset,
+ HValue* typecheck = NULL)
+ : is_in_object_(is_in_object),
offset_(offset) {
+ ASSERT(object != NULL);
+ SetOperandAt(0, object);
+ SetOperandAt(1, typecheck != NULL ? typecheck : object);
+
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnMaps);
@@ -5200,7 +5172,24 @@ class HLoadNamedField: public HUnaryOperation {
}
}
+ static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object,
+ HValue* typecheck,
+ HType type = HType::Tagged()) {
+ HLoadNamedField* result = new(zone) HLoadNamedField(
+ object, true, JSArray::kLengthOffset, typecheck);
+ result->set_type(type);
+ result->SetGVNFlag(kDependsOnArrayLengths);
+ result->ClearGVNFlag(kDependsOnInobjectFields);
+ return result;
+ }
+
HValue* object() { return OperandAt(0); }
+ HValue* typecheck() {
+ ASSERT(HasTypeCheck());
+ return OperandAt(1);
+ }
+
+ bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
bool is_in_object() const { return is_in_object_; }
int offset() const { return offset_; }
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index 14feb5f13..abff7b778 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -113,6 +113,10 @@ void HBasicBlock::AddInstruction(HInstruction* instr) {
ASSERT(!IsStartBlock() || !IsFinished());
ASSERT(!instr->IsLinked());
ASSERT(!IsFinished());
+ // Make sure that we never add instructions without knowing
+ // what the previous ast id is.
+ ASSERT(instr->IsSimulate() || instr->IsGoto() ||
+ !last_environment()->previous_ast_id().IsNone());
if (first_ == NULL) {
HBlockEntry* entry = new(zone()) HBlockEntry();
entry->InitializeAsFirst(this);
@@ -211,10 +215,12 @@ void HBasicBlock::AddLeaveInlined(HValue* return_value,
}
-void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
+void HBasicBlock::SetInitialEnvironment(HEnvironment* env,
+ BailoutId previous_ast_id) {
ASSERT(!HasEnvironment());
ASSERT(first() == NULL);
UpdateEnvironment(env);
+ env->set_previous_ast_id(previous_ast_id);
}
@@ -225,13 +231,17 @@ void HBasicBlock::SetJoinId(BailoutId ast_id) {
HBasicBlock* predecessor = predecessors_[i];
ASSERT(predecessor->end()->IsGoto());
HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
- // We only need to verify the ID once.
ASSERT(i != 0 ||
(predecessor->last_environment()->closure().is_null() ||
predecessor->last_environment()->closure()->shared()
->VerifyBailoutId(ast_id)));
simulate->set_ast_id(ast_id);
}
+ HEnvironment* last_environment = this->last_environment();
+ ASSERT(last_environment || IsFinished());
+ if (last_environment != NULL) {
+ last_environment->set_previous_ast_id(ast_id);
+ }
}
@@ -291,7 +301,9 @@ void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
}
} else if (!HasEnvironment() && !IsFinished()) {
ASSERT(!IsLoopHeader());
- SetInitialEnvironment(pred->last_environment()->Copy());
+ HEnvironment* new_env = pred->last_environment()->Copy();
+ SetInitialEnvironment(new_env,
+ pred->last_environment()->previous_ast_id());
}
predecessors_.Add(pred, zone());
@@ -542,18 +554,6 @@ void HGraph::Verify(bool do_full_verify) const {
HPhi* phi = block->phis()->at(j);
phi->Verify();
}
-
- // Check that all join blocks have predecessors that end with an
- // unconditional goto and agree on their environment node id.
- if (block->predecessors()->length() >= 2) {
- BailoutId id =
- block->predecessors()->first()->last_environment()->ast_id();
- for (int k = 0; k < block->predecessors()->length(); k++) {
- HBasicBlock* predecessor = block->predecessors()->at(k);
- ASSERT(predecessor->end()->IsGoto());
- ASSERT(predecessor->last_environment()->ast_id() == id);
- }
- }
}
// Check special property of first block to have no predecessors.
@@ -637,50 +637,64 @@ DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false)
#undef DEFINE_GET_CONSTANT
-HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id)
+HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder)
: builder_(builder),
finished_(false),
- id_(id) {
+ id_(builder->current_block()->last_environment()->previous_ast_id()) {
HEnvironment* env = builder->environment();
- failure_block_ = builder->CreateBasicBlock(env->Copy());
- merge_block_ = builder->CreateBasicBlock(env->Copy());
+ failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory(), id_);
+ merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory(), id_);
}
-void HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) {
+HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) {
HEnvironment* env = builder_->environment();
HIsNilAndBranch* compare =
new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue);
- HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy());
- HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy());
+ HBasicBlock* success_block =
+ builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
+ HBasicBlock* failure_block =
+ builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
compare->SetSuccessorAt(0, failure_block);
compare->SetSuccessorAt(1, success_block);
failure_block->Goto(failure_block_);
builder_->current_block()->Finish(compare);
builder_->set_current_block(success_block);
+ return compare;
}
-void HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, HValue* right) {
+HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left,
+ HValue* right,
+ Token::Value op) {
HEnvironment* env = builder_->environment();
HCompareIDAndBranch* compare =
- new(zone()) HCompareIDAndBranch(left, right, Token::EQ);
+ new(zone()) HCompareIDAndBranch(left, right, op);
compare->AssumeRepresentation(Representation::Integer32());
- HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy());
- HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy());
+ HBasicBlock* success_block =
+ builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
+ HBasicBlock* failure_block =
+ builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
compare->SetSuccessorAt(0, success_block);
compare->SetSuccessorAt(1, failure_block);
failure_block->Goto(failure_block_);
builder_->current_block()->Finish(compare);
builder_->set_current_block(success_block);
+ return compare;
+}
+
+
+HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left,
+ HValue* right) {
+ return CheckIntegerCompare(left, right, Token::EQ);
}
void HGraphBuilder::CheckBuilder::End() {
ASSERT(!finished_);
builder_->current_block()->Goto(merge_block_);
- failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
failure_block_->SetJoinId(id_);
+ failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
builder_->set_current_block(merge_block_);
merge_block_->SetJoinId(id_);
finished_ = true;
@@ -692,18 +706,19 @@ HConstant* HGraph::GetInvalidContext() {
}
-HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id)
+HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
: builder_(builder),
finished_(false),
- id_(id) {
+ did_else_(false),
+ id_(builder->current_block()->last_environment()->previous_ast_id()) {
HEnvironment* env = builder->environment();
- first_true_block_ = builder->CreateBasicBlock(env->Copy());
+ first_true_block_ = builder->CreateBasicBlock(env->Copy(), id_);
last_true_block_ = NULL;
- first_false_block_ = builder->CreateBasicBlock(env->Copy());
+ first_false_block_ = builder->CreateBasicBlock(env->Copy(), id_);
}
-HInstruction* HGraphBuilder::IfBuilder::BeginTrue(
+HInstruction* HGraphBuilder::IfBuilder::BeginIf(
HValue* left,
HValue* right,
Token::Value token,
@@ -721,21 +736,46 @@ HInstruction* HGraphBuilder::IfBuilder::BeginTrue(
}
-void HGraphBuilder::IfBuilder::BeginFalse() {
+HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual(
+ HValue* left,
+ HValue* right) {
+ HCompareObjectEqAndBranch* compare =
+ new(zone()) HCompareObjectEqAndBranch(left, right);
+ compare->SetSuccessorAt(0, first_true_block_);
+ compare->SetSuccessorAt(1, first_false_block_);
+ builder_->current_block()->Finish(compare);
+ builder_->set_current_block(first_true_block_);
+ return compare;
+}
+
+
+HInstruction* HGraphBuilder::IfBuilder::BeginIfMapEquals(HValue* value,
+ Handle<Map> map) {
+ HCompareMap* compare = new(zone())
+ HCompareMap(value, map, first_true_block_, first_false_block_);
+ builder_->current_block()->Finish(compare);
+ builder_->set_current_block(first_true_block_);
+ return compare;
+}
+
+
+void HGraphBuilder::IfBuilder::BeginElse() {
last_true_block_ = builder_->current_block();
ASSERT(!last_true_block_->IsFinished());
builder_->set_current_block(first_false_block_);
+ did_else_ = true;
}
void HGraphBuilder::IfBuilder::End() {
ASSERT(!finished_);
+ if (!did_else_) BeginElse();
ASSERT(!last_true_block_->IsFinished());
HBasicBlock* last_false_block = builder_->current_block();
ASSERT(!last_false_block->IsFinished());
HEnvironment* merge_env =
- last_true_block_->last_environment()->Copy();
- merge_block_ = builder_->CreateBasicBlock(merge_env);
+ last_true_block_->last_environment()->CopyWithoutHistory();
+ merge_block_ = builder_->CreateBasicBlock(merge_env, id_);
last_true_block_->Goto(merge_block_);
last_false_block->Goto(merge_block_);
merge_block_->SetJoinId(id_);
@@ -746,14 +786,13 @@ void HGraphBuilder::IfBuilder::End() {
HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
HValue* context,
- LoopBuilder::Direction direction,
- BailoutId id)
+ LoopBuilder::Direction direction)
: builder_(builder),
context_(context),
direction_(direction),
- id_(id),
+ id_(builder->current_block()->last_environment()->previous_ast_id()),
finished_(false) {
- header_block_ = builder->CreateLoopHeaderBlock();
+ header_block_ = builder->CreateLoopHeaderBlock(id_);
body_block_ = NULL;
exit_block_ = NULL;
}
@@ -774,8 +813,8 @@ HValue* HGraphBuilder::LoopBuilder::BeginBody(
HEnvironment* body_env = env->Copy();
HEnvironment* exit_env = env->Copy();
- body_block_ = builder_->CreateBasicBlock(body_env);
- exit_block_ = builder_->CreateBasicBlock(exit_env);
+ body_block_ = builder_->CreateBasicBlock(body_env, id_);
+ exit_block_ = builder_->CreateBasicBlock(exit_env, id_);
// Remove the phi from the expression stack
body_env->Pop();
@@ -856,6 +895,7 @@ void HGraphBuilder::AddSimulate(BailoutId id,
RemovableSimulate removable) {
ASSERT(current_block() != NULL);
current_block()->AddSimulate(id, removable);
+ environment()->set_previous_ast_id(id);
}
@@ -890,17 +930,18 @@ HReturn* HGraphBuilder::AddReturn(HValue* value) {
}
-HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
+HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env,
+ BailoutId previous_ast_id) {
HBasicBlock* b = graph()->CreateBasicBlock();
- b->SetInitialEnvironment(env);
+ b->SetInitialEnvironment(env, previous_ast_id);
return b;
}
-HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
+HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock(BailoutId previous_ast_id) {
HBasicBlock* header = graph()->CreateBasicBlock();
HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
- header->SetInitialEnvironment(entry_env);
+ header->SetInitialEnvironment(entry_env, previous_ast_id);
header->AttachLoopInformation();
return header;
}
@@ -965,7 +1006,8 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(
HValue* val,
HValue* load_dependency,
ElementsKind elements_kind,
- bool is_store) {
+ bool is_store,
+ KeyedAccessStoreMode store_mode) {
Zone* zone = this->zone();
if (is_store) {
ASSERT(val != NULL);
@@ -993,6 +1035,99 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(
}
+HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* key,
+ bool is_js_array) {
+ BailoutId ast_id = environment()->previous_ast_id();
+ Zone* zone = this->zone();
+ IfBuilder length_checker(this);
+
+ length_checker.BeginIf(length, key, Token::EQ);
+
+ HValue* current_capacity =
+ AddInstruction(new(zone) HFixedArrayBaseLength(elements));
+
+ IfBuilder capacity_checker(this);
+
+ capacity_checker.BeginIf(length, current_capacity, Token::EQ);
+
+ HValue* context = environment()->LookupContext();
+
+ HValue* new_capacity =
+ BuildNewElementsCapacity(context, current_capacity);
+
+ HValue* new_elements = BuildGrowElementsCapacity(object, elements,
+ kind, length,
+ new_capacity);
+
+ environment()->Push(new_elements);
+ capacity_checker.BeginElse();
+
+ environment()->Push(elements);
+ capacity_checker.End();
+
+ if (is_js_array) {
+ HValue* new_length = AddInstruction(
+ HAdd::New(zone, context, length, graph_->GetConstant1()));
+ new_length->ChangeRepresentation(Representation::Integer32());
+ new_length->ClearFlag(HValue::kCanOverflow);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
+
+ Factory* factory = isolate()->factory();
+ HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
+ object,
+ factory->length_field_string(),
+ new_length, true,
+ JSArray::kLengthOffset));
+ length_store->SetGVNFlag(kChangesArrayLengths);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
+ }
+
+ length_checker.BeginElse();
+
+ AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+ environment()->Push(elements);
+
+ length_checker.End();
+
+ return environment()->Pop();
+}
+
+
+HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length) {
+ Zone* zone = this->zone();
+ Heap* heap = isolate()->heap();
+
+ IfBuilder cow_checker(this);
+
+ cow_checker.BeginIfMapEquals(elements,
+ Handle<Map>(heap->fixed_cow_array_map()));
+
+ HValue* capacity =
+ AddInstruction(new(zone) HFixedArrayBaseLength(elements));
+
+ HValue* new_elements = BuildGrowElementsCapacity(object, elements,
+ kind, length,
+ capacity);
+
+ environment()->Push(new_elements);
+
+ cow_checker.BeginElse();
+
+ environment()->Push(elements);
+
+ cow_checker.End();
+
+ return environment()->Pop();
+}
+
+
HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HValue* object,
HValue* key,
@@ -1001,7 +1136,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
bool is_js_array,
ElementsKind elements_kind,
bool is_store,
+ KeyedAccessStoreMode store_mode,
Representation checked_index_representation) {
+ ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
Zone* zone = this->zone();
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency
// on a HElementsTransition instruction. The flag can also be removed if the
@@ -1017,46 +1154,91 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
}
bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
bool fast_elements = IsFastObjectElementsKind(elements_kind);
- HInstruction* elements =
+ HValue* elements =
AddInstruction(new(zone) HLoadElements(object, mapcheck));
- if (is_store && (fast_elements || fast_smi_only_elements)) {
+ if (is_store && (fast_elements || fast_smi_only_elements) &&
+ store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
HCheckMaps* check_cow_map = new(zone) HCheckMaps(
elements, isolate()->factory()->fixed_array_map(), zone);
check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
AddInstruction(check_cow_map);
}
HInstruction* length = NULL;
- HInstruction* checked_key = NULL;
- if (IsExternalArrayElementsKind(elements_kind)) {
+ if (is_js_array) {
+ length = AddInstruction(
+ HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi()));
+ } else {
length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
- checked_key = AddBoundsCheck(
- key, length, ALLOW_SMI_KEY, checked_index_representation);
- HLoadExternalArrayPointer* external_elements =
- new(zone) HLoadExternalArrayPointer(elements);
- AddInstruction(external_elements);
- return BuildExternalArrayElementAccess(
- external_elements, checked_key, val, mapcheck,
- elements_kind, is_store);
+ }
+ HValue* checked_key = NULL;
+ if (IsExternalArrayElementsKind(elements_kind)) {
+ if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
+ HLoadExternalArrayPointer* external_elements =
+ new(zone) HLoadExternalArrayPointer(elements);
+ AddInstruction(external_elements);
+ IfBuilder length_checker(this);
+ length_checker.BeginIf(key, length, Token::LT);
+ CheckBuilder negative_checker(this);
+ HValue* bounds_check = negative_checker.CheckIntegerCompare(
+ key, graph()->GetConstant0(), Token::GTE);
+ negative_checker.End();
+ HInstruction* result = BuildExternalArrayElementAccess(
+ external_elements, key, val, bounds_check,
+ elements_kind, is_store);
+ AddInstruction(result);
+ length_checker.End();
+ return result;
+ } else {
+ ASSERT(store_mode == STANDARD_STORE);
+ checked_key = AddBoundsCheck(
+ key, length, ALLOW_SMI_KEY, checked_index_representation);
+ HLoadExternalArrayPointer* external_elements =
+ new(zone) HLoadExternalArrayPointer(elements);
+ AddInstruction(external_elements);
+ return AddInstruction(BuildExternalArrayElementAccess(
+ external_elements, checked_key, val, mapcheck,
+ elements_kind, is_store));
+ }
}
ASSERT(fast_smi_only_elements ||
fast_elements ||
IsFastDoubleElementsKind(elements_kind));
- if (is_js_array) {
- length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
- HType::Smi()));
+
+ if (is_store && IsFastSmiElementsKind(elements_kind) &&
+ !val->type().IsSmi()) {
+ AddInstruction(new(zone) HCheckSmi(val));
+ }
+
+ if (IsGrowStoreMode(store_mode)) {
+ elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
+ length, key, is_js_array);
+ checked_key = key;
} else {
- length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
+ checked_key = AddBoundsCheck(
+ key, length, ALLOW_SMI_KEY, checked_index_representation);
+
+ if (is_store && (fast_elements || fast_smi_only_elements)) {
+ if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
+ elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
+ length);
+ } else {
+ HCheckMaps* check_cow_map = new(zone) HCheckMaps(
+ elements, isolate()->factory()->fixed_array_map(), zone);
+ check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
+ AddInstruction(check_cow_map);
+ }
+ }
}
- checked_key = AddBoundsCheck(
- key, length, ALLOW_SMI_KEY, checked_index_representation);
- return BuildFastElementAccess(elements, checked_key, val, mapcheck,
- elements_kind, is_store);
+ return AddInstruction(
+ BuildFastElementAccess(elements, checked_key, val, mapcheck,
+ elements_kind, is_store, store_mode));
}
-HValue* HGraphBuilder::BuildAllocateElements(HContext* context,
+HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
ElementsKind kind,
HValue* capacity) {
+ BailoutId ast_id = current_block()->last_environment()->previous_ast_id();
Zone* zone = this->zone();
int elements_size = IsFastDoubleElementsKind(kind)
@@ -1096,14 +1278,14 @@ HValue* HGraphBuilder::BuildAllocateElements(HContext* context,
Handle<Map> map = IsFastDoubleElementsKind(kind)
? factory->fixed_double_array_map()
: factory->fixed_array_map();
- BuildStoreMap(elements, map, BailoutId::StubEntry());
+ BuildStoreMap(elements, map, ast_id);
Handle<String> fixed_array_length_field_name = factory->length_field_string();
HInstruction* store_length =
new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
capacity, true, FixedArray::kLengthOffset);
AddInstruction(store_length);
- AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
return elements;
}
@@ -1120,7 +1302,7 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
true, JSObject::kMapOffset);
store_map->SetGVNFlag(kChangesMaps);
AddInstruction(store_map);
- AddSimulate(id, FIXED_SIMULATE);
+ AddSimulate(id, REMOVABLE_SIMULATE);
return store_map;
}
@@ -1135,17 +1317,131 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
}
-void HGraphBuilder::BuildCopyElements(HContext* context,
+HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
+ HValue* old_capacity) {
+ Zone* zone = this->zone();
+ HValue* half_old_capacity =
+ AddInstruction(HShr::New(zone, context, old_capacity,
+ graph_->GetConstant1()));
+ half_old_capacity->ChangeRepresentation(Representation::Integer32());
+ half_old_capacity->ClearFlag(HValue::kCanOverflow);
+
+ HValue* new_capacity = AddInstruction(
+ HAdd::New(zone, context, half_old_capacity, old_capacity));
+ new_capacity->ChangeRepresentation(Representation::Integer32());
+ new_capacity->ClearFlag(HValue::kCanOverflow);
+
+ HValue* min_growth =
+ AddInstruction(new(zone) HConstant(16, Representation::Integer32()));
+
+ new_capacity = AddInstruction(
+ HAdd::New(zone, context, new_capacity, min_growth));
+ new_capacity->ChangeRepresentation(Representation::Integer32());
+ new_capacity->ClearFlag(HValue::kCanOverflow);
+
+ return new_capacity;
+}
+
+
+void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
+ Zone* zone = this->zone();
+ Heap* heap = isolate()->heap();
+ int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize
+ : kPointerSize;
+ int max_size = heap->MaxNewSpaceAllocationSize() / element_size;
+ max_size -= JSArray::kSize / element_size;
+ HConstant* max_size_constant =
+ new(zone) HConstant(max_size, Representation::Integer32());
+ AddInstruction(max_size_constant);
+ // Since we're forcing Integer32 representation for this HBoundsCheck,
+ // there's no need to Smi-check the index.
+ AddInstruction(new(zone)
+ HBoundsCheck(length, max_size_constant,
+ DONT_ALLOW_SMI_KEY, Representation::Integer32()));
+}
+
+
+HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* new_capacity) {
+ Zone* zone = this->zone();
+ HValue* context = environment()->LookupContext();
+
+ BuildNewSpaceArrayCheck(new_capacity, kind);
+
+ HValue* new_elements =
+ BuildAllocateElements(context, kind, new_capacity);
+
+ BuildCopyElements(context, elements, kind,
+ new_elements, kind,
+ length, new_capacity);
+
+ Factory* factory = isolate()->factory();
+ HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
+ object,
+ factory->elements_field_string(),
+ new_elements, true,
+ JSArray::kElementsOffset));
+ elements_store->SetGVNFlag(kChangesElementsPointer);
+
+ return new_elements;
+}
+
+
+void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
+ HValue* elements,
+ ElementsKind elements_kind,
+ HValue* from,
+ HValue* to) {
+ BailoutId ast_id = current_block()->last_environment()->previous_ast_id();
+ // Fast elements kinds need to be initialized in case statements below cause
+ // a garbage collection.
+ Factory* factory = isolate()->factory();
+
+ double nan_double = FixedDoubleArray::hole_nan_as_double();
+ Zone* zone = this->zone();
+ HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
+ ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
+ Representation::Tagged()))
+ : AddInstruction(new(zone) HConstant(nan_double,
+ Representation::Double()));
+
+ LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
+
+ HValue* key = builder.BeginBody(from, to, Token::LT);
+
+ AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind));
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
+
+ builder.EndBody();
+}
+
+
+void HGraphBuilder::BuildCopyElements(HValue* context,
HValue* from_elements,
ElementsKind from_elements_kind,
HValue* to_elements,
ElementsKind to_elements_kind,
- HValue* length) {
- LoopBuilder builder(this, context, LoopBuilder::kPostIncrement,
- BailoutId::StubEntry());
+ HValue* length,
+ HValue* capacity) {
+ BailoutId ast_id = environment()->previous_ast_id();
+ bool pre_fill_with_holes =
+ IsFastDoubleElementsKind(from_elements_kind) &&
+ IsFastObjectElementsKind(to_elements_kind);
- HValue* key = builder.BeginBody(graph()->GetConstant0(),
- length, Token::LT);
+ if (pre_fill_with_holes) {
+ // If the copy might trigger a GC, make sure that the FixedArray is
+ // pre-initialized with holes to make sure that it's always in a consistent
+ // state.
+ BuildFillElementsWithHole(context, to_elements, to_elements_kind,
+ graph()->GetConstant0(), capacity);
+ }
+
+ LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
+
+ HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
HValue* element =
AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL,
@@ -1154,9 +1450,15 @@ void HGraphBuilder::BuildCopyElements(HContext* context,
AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element,
to_elements_kind));
- AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE);
+ AddSimulate(ast_id, REMOVABLE_SIMULATE);
builder.EndBody();
+
+ if (!pre_fill_with_holes && length != capacity) {
+ // Fill unused capacity with the hole.
+ BuildFillElementsWithHole(context, to_elements, to_elements_kind,
+ key, capacity);
+ }
}
@@ -1253,9 +1555,9 @@ HGraph::HGraph(CompilationInfo* info)
start_environment_ =
new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
}
- start_environment_->set_ast_id(BailoutId::FunctionEntry());
entry_block_ = CreateBasicBlock();
- entry_block_->SetInitialEnvironment(start_environment_);
+ entry_block_->SetInitialEnvironment(start_environment_,
+ BailoutId::FunctionEntry());
}
@@ -3813,6 +4115,10 @@ void HOptimizedGraphBuilder::VisitExpressions(
bool HOptimizedGraphBuilder::BuildGraph() {
+ if (info()->function()->is_generator()) {
+ Bailout("function is a generator");
+ return false;
+ }
Scope* scope = info()->scope();
if (scope->HasIllegalRedeclaration()) {
Bailout("function with illegal redeclaration");
@@ -3840,7 +4146,8 @@ bool HOptimizedGraphBuilder::BuildGraph() {
// values (but not instructions), present in the initial environment and
// not replayed by the Lithium translation.
HEnvironment* initial_env = environment()->CopyWithoutHistory();
- HBasicBlock* body_entry = CreateBasicBlock(initial_env);
+ HBasicBlock* body_entry = CreateBasicBlock(initial_env,
+ BailoutId::FunctionEntry());
current_block()->Goto(body_entry);
body_entry->SetJoinId(BailoutId::FunctionEntry());
set_current_block(body_entry);
@@ -4780,19 +5087,7 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
typecheck->SetSuccessorAt(1, not_spec_object);
current_block()->Finish(typecheck);
if_spec_object->AddLeaveInlined(return_value, state);
- if (!FLAG_harmony_symbols) {
- not_spec_object->AddLeaveInlined(receiver, state);
- } else {
- HHasInstanceTypeAndBranch* symbolcheck =
- new(zone()) HHasInstanceTypeAndBranch(return_value, SYMBOL_TYPE);
- HBasicBlock* is_symbol = graph()->CreateBasicBlock();
- HBasicBlock* not_symbol = graph()->CreateBasicBlock();
- symbolcheck->SetSuccessorAt(0, is_symbol);
- symbolcheck->SetSuccessorAt(1, not_symbol);
- not_spec_object->Finish(symbolcheck);
- is_symbol->AddLeaveInlined(return_value, state);
- not_symbol->AddLeaveInlined(receiver, state);
- }
+ not_spec_object->AddLeaveInlined(receiver, state);
}
} else if (state->inlining_kind() == SETTER_CALL_RETURN) {
// Return from an inlined setter call. The returned value is never used, the
@@ -5098,7 +5393,7 @@ void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
ASSERT(current_block()->HasPredecessor());
ASSERT(current_block() != NULL);
bool osr_entry = PreProcessOsrEntry(stmt);
- HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
current_block()->Goto(loop_entry);
set_current_block(loop_entry);
if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5141,7 +5436,7 @@ void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
ASSERT(current_block()->HasPredecessor());
ASSERT(current_block() != NULL);
bool osr_entry = PreProcessOsrEntry(stmt);
- HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
current_block()->Goto(loop_entry);
set_current_block(loop_entry);
if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5188,7 +5483,7 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
}
ASSERT(current_block() != NULL);
bool osr_entry = PreProcessOsrEntry(stmt);
- HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
current_block()->Goto(loop_entry);
set_current_block(loop_entry);
if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5283,7 +5578,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
HForInCacheArray::cast(index_cache));
bool osr_entry = PreProcessOsrEntry(stmt);
- HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
current_block()->Goto(loop_entry);
set_current_block(loop_entry);
if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5996,6 +6291,12 @@ static int ComputeLoadStoreFieldIndex(Handle<Map> type,
}
+void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) {
+ AddInstruction(new(zone()) HCheckNonSmi(object));
+ AddInstruction(new(zone()) HCheckMaps(object, map, zone()));
+}
+
+
void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object,
Handle<Map> map) {
AddInstruction(new(zone()) HCheckNonSmi(object));
@@ -6107,15 +6408,40 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
}
-void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
+bool HOptimizedGraphBuilder::HandlePolymorphicArrayLengthLoad(
Property* expr,
HValue* object,
SmallMapList* types,
Handle<String> name) {
+ if (!name->Equals(isolate()->heap()->length_string())) return false;
+
+ for (int i = 0; i < types->length(); i++) {
+ if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false;
+ }
+
+ AddInstruction(new(zone()) HCheckNonSmi(object));
+ HInstruction* typecheck =
+ AddInstruction(HCheckInstanceType::NewIsJSArray(object, zone()));
+ HInstruction* instr =
+ HLoadNamedField::NewArrayLength(zone(), object, typecheck);
+ instr->set_position(expr->position());
+ ast_context()->ReturnInstruction(instr, expr->id());
+ return true;
+}
+
+
+void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
+ HValue* object,
+ SmallMapList* types,
+ Handle<String> name) {
int count = 0;
int previous_field_offset = 0;
bool previous_field_is_in_object = false;
bool is_monomorphic_field = true;
+
+ if (HandlePolymorphicArrayLengthLoad(expr, object, types, name))
+ return;
+
Handle<Map> map;
LookupResult lookup(isolate());
for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
@@ -6682,6 +7008,12 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
}
+void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
+ // Generators are not optimized, so we should never get here.
+ UNREACHABLE();
+}
+
+
void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
@@ -6751,16 +7083,25 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<Map> map) {
// Handle a load from a known field.
ASSERT(!map->is_dictionary_map());
+
+ // Handle access to various length properties
+ if (name->Equals(isolate()->heap()->length_string())) {
+ if (map->instance_type() == JS_ARRAY_TYPE) {
+ AddCheckMapsWithTransitions(object, map);
+ return HLoadNamedField::NewArrayLength(zone(), object, object);
+ }
+ }
+
LookupResult lookup(isolate());
map->LookupDescriptor(NULL, *name, &lookup);
if (lookup.IsField()) {
- AddCheckMapsWithTransitions(object, map);
+ AddCheckMap(object, map);
return BuildLoadNamedField(object, map, &lookup);
}
// Handle a load of a constant known function.
if (lookup.IsConstantFunction()) {
- AddCheckMapsWithTransitions(object, map);
+ AddCheckMap(object, map);
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
return new(zone()) HConstant(function, Representation::Tagged());
}
@@ -6771,7 +7112,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<JSObject> prototype(JSObject::cast(map->prototype()));
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
- AddCheckMapsWithTransitions(object, map);
+ AddCheckMap(object, map);
HInstruction* holder_value = AddInstruction(
new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
return BuildLoadNamedField(holder_value, holder_map, &lookup);
@@ -6782,7 +7123,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<JSObject> prototype(JSObject::cast(map->prototype()));
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
- AddCheckMapsWithTransitions(object, map);
+ AddCheckMap(object, map);
AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map));
return new(zone()) HConstant(function, Representation::Tagged());
@@ -6806,7 +7147,8 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
HValue* val,
HValue* dependency,
Handle<Map> map,
- bool is_store) {
+ bool is_store,
+ KeyedAccessStoreMode store_mode) {
HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
zone(), dependency);
AddInstruction(mapcheck);
@@ -6816,7 +7158,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
return BuildUncheckedMonomorphicElementAccess(
object, key, val,
mapcheck, map->instance_type() == JS_ARRAY_TYPE,
- map->elements_kind(), is_store);
+ map->elements_kind(), is_store, store_mode);
}
@@ -6871,7 +7213,7 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
object, key, val, check_maps,
most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
most_general_consolidated_map->elements_kind(),
- false);
+ false, STANDARD_STORE);
return instr;
}
@@ -6884,6 +7226,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
BailoutId ast_id,
int position,
bool is_store,
+ KeyedAccessStoreMode store_mode,
bool* has_side_effects) {
*has_side_effects = false;
AddInstruction(new(zone()) HCheckNonSmi(object));
@@ -6894,7 +7237,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
HInstruction* consolidated_load =
TryBuildConsolidatedElementLoad(object, key, val, maps);
if (consolidated_load != NULL) {
- AddInstruction(consolidated_load);
*has_side_effects |= consolidated_load->HasObservableSideEffects();
if (position != RelocInfo::kNoPosition) {
consolidated_load->set_position(position);
@@ -6961,8 +7303,9 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key));
} else {
- instr = AddInstruction(BuildMonomorphicElementAccess(
- object, key, val, transition, untransitionable_map, is_store));
+ instr = BuildMonomorphicElementAccess(
+ object, key, val, transition, untransitionable_map, is_store,
+ store_mode);
}
*has_side_effects |= instr->HasObservableSideEffects();
if (position != RelocInfo::kNoPosition) instr->set_position(position);
@@ -7038,12 +7381,13 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
set_current_block(if_jsarray);
HInstruction* length;
- length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
- HType::Smi()));
+ length = AddInstruction(
+ HLoadNamedField::NewArrayLength(zone(), object, typecheck,
+ HType::Smi()));
checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind_branch,
- elements_kind, is_store));
+ elements_kind, is_store, STANDARD_STORE));
if (!is_store) {
Push(access);
}
@@ -7059,7 +7403,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind_branch,
- elements_kind, is_store));
+ elements_kind, is_store, STANDARD_STORE));
} else if (elements_kind == DICTIONARY_ELEMENTS) {
if (is_store) {
access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
@@ -7105,23 +7449,26 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
if (map->has_slow_elements_kind()) {
instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
: BuildLoadKeyedGeneric(obj, key);
+ AddInstruction(instr);
} else {
AddInstruction(new(zone()) HCheckNonSmi(obj));
- instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store);
+ instr = BuildMonomorphicElementAccess(
+ obj, key, val, NULL, map, is_store, expr->GetStoreMode());
}
} else if (expr->GetReceiverTypes() != NULL &&
!expr->GetReceiverTypes()->is_empty()) {
return HandlePolymorphicElementAccess(
- obj, key, val, expr, ast_id, position, is_store, has_side_effects);
+ obj, key, val, expr, ast_id, position, is_store,
+ expr->GetStoreMode(), has_side_effects);
} else {
if (is_store) {
instr = BuildStoreKeyedGeneric(obj, key, val);
} else {
instr = BuildLoadKeyedGeneric(obj, key);
}
+ AddInstruction(instr);
}
if (position != RelocInfo::kNoPosition) instr->set_position(position);
- AddInstruction(instr);
*has_side_effects = instr->HasObservableSideEffects();
return instr;
}
@@ -7237,13 +7584,7 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
CHECK_ALIVE(VisitForValue(expr->obj()));
HInstruction* instr = NULL;
- if (expr->AsProperty()->IsArrayLength()) {
- HValue* array = Pop();
- AddInstruction(new(zone()) HCheckNonSmi(array));
- HInstruction* mapcheck =
- AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone()));
- instr = new(zone()) HJSArrayLength(array, mapcheck);
- } else if (expr->IsStringLength()) {
+ if (expr->IsStringLength()) {
HValue* string = Pop();
AddInstruction(new(zone()) HCheckNonSmi(string));
AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
@@ -7772,7 +8113,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
AddSimulate(return_id);
current_block()->UpdateEnvironment(inner_env);
-
+ inner_env->set_previous_ast_id(BailoutId::FunctionEntry());
ZoneList<HValue*>* arguments_values = NULL;
// If the function uses arguments copy current arguments values
@@ -9772,16 +10113,6 @@ void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
}
-void HOptimizedGraphBuilder::GenerateIsSymbol(CallRuntime* call) {
- ASSERT(call->arguments()->length() == 1);
- CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
- HValue* value = Pop();
- HHasInstanceTypeAndBranch* result =
- new(zone()) HHasInstanceTypeAndBranch(value, SYMBOL_TYPE);
- return ast_context()->ReturnControl(result, call->id());
-}
-
-
void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
ASSERT(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -10295,6 +10626,7 @@ HEnvironment::HEnvironment(HEnvironment* outer,
pop_count_(0),
push_count_(0),
ast_id_(BailoutId::None()),
+ previous_ast_id_(BailoutId::None()),
zone_(zone) {
Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
}
@@ -10311,6 +10643,7 @@ HEnvironment::HEnvironment(Zone* zone, int parameter_count)
pop_count_(0),
push_count_(0),
ast_id_(BailoutId::None()),
+ previous_ast_id_(BailoutId::None()),
zone_(zone) {
Initialize(parameter_count, 0, 0);
}
@@ -10327,6 +10660,7 @@ HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
pop_count_(0),
push_count_(0),
ast_id_(other->ast_id()),
+ previous_ast_id_(BailoutId::None()),
zone_(zone) {
Initialize(other);
}
@@ -10347,6 +10681,7 @@ HEnvironment::HEnvironment(HEnvironment* outer,
pop_count_(0),
push_count_(0),
ast_id_(BailoutId::None()),
+ previous_ast_id_(BailoutId::None()),
zone_(zone) {
}
diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h
index 7f5326bcb..ef3679eca 100644
--- a/deps/v8/src/hydrogen.h
+++ b/deps/v8/src/hydrogen.h
@@ -108,7 +108,7 @@ class HBasicBlock: public ZoneObject {
bool Dominates(HBasicBlock* other) const;
int LoopNestingDepth() const;
- void SetInitialEnvironment(HEnvironment* env);
+ void SetInitialEnvironment(HEnvironment* env, BailoutId previous_id);
void ClearEnvironment() { last_environment_ = NULL; }
bool HasEnvironment() const { return last_environment_ != NULL; }
void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; }
@@ -483,6 +483,8 @@ class HEnvironment: public ZoneObject {
BailoutId ast_id() const { return ast_id_; }
void set_ast_id(BailoutId id) { ast_id_ = id; }
+ BailoutId previous_ast_id() const { return previous_ast_id_; }
+ void set_previous_ast_id(BailoutId id) { previous_ast_id_ = id; }
HEnterInlined* entry() const { return entry_; }
void set_entry(HEnterInlined* entry) { entry_ = entry; }
@@ -644,6 +646,7 @@ class HEnvironment: public ZoneObject {
int pop_count_;
int push_count_;
BailoutId ast_id_;
+ BailoutId previous_ast_id_;
Zone* zone_;
};
@@ -891,8 +894,9 @@ class HGraphBuilder {
protected:
virtual bool BuildGraph() = 0;
- HBasicBlock* CreateBasicBlock(HEnvironment* env);
- HBasicBlock* CreateLoopHeaderBlock();
+ HBasicBlock* CreateBasicBlock(HEnvironment* envy,
+ BailoutId previous_ast_id);
+ HBasicBlock* CreateLoopHeaderBlock(BailoutId previous_ast_id);
// Building common constructs
HInstruction* BuildExternalArrayElementAccess(
@@ -909,7 +913,20 @@ class HGraphBuilder {
HValue* val,
HValue* dependency,
ElementsKind elements_kind,
- bool is_store);
+ bool is_store,
+ KeyedAccessStoreMode store_mode);
+
+ HValue* BuildCheckForCapacityGrow(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* key,
+ bool is_js_array);
+
+ HValue* BuildCopyElementsOnWrite(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length);
HInstruction* BuildUncheckedMonomorphicElementAccess(
HValue* object,
@@ -919,6 +936,7 @@ class HGraphBuilder {
bool is_js_array,
ElementsKind elements_kind,
bool is_store,
+ KeyedAccessStoreMode store_mode,
Representation checked_index_representation = Representation::None());
HInstruction* BuildStoreMap(HValue* object, HValue* map, BailoutId id);
@@ -926,13 +944,14 @@ class HGraphBuilder {
class CheckBuilder {
public:
- CheckBuilder(HGraphBuilder* builder, BailoutId id);
+ explicit CheckBuilder(HGraphBuilder* builder);
~CheckBuilder() {
if (!finished_) End();
}
- void CheckNotUndefined(HValue* value);
- void CheckIntegerEq(HValue* left, HValue* right);
+ HValue* CheckNotUndefined(HValue* value);
+ HValue* CheckIntegerCompare(HValue* left, HValue* right, Token::Value op);
+ HValue* CheckIntegerEq(HValue* left, HValue* right);
void End();
private:
@@ -947,17 +966,19 @@ class HGraphBuilder {
class IfBuilder {
public:
- IfBuilder(HGraphBuilder* builder, BailoutId id);
+ explicit IfBuilder(HGraphBuilder* builder);
~IfBuilder() {
if (!finished_) End();
}
- HInstruction* BeginTrue(
+ HInstruction* BeginIf(
HValue* left,
HValue* right,
Token::Value token,
Representation input_representation = Representation::Integer32());
- void BeginFalse();
+ HInstruction* BeginIfObjectsEqual(HValue* left, HValue* right);
+ HInstruction* BeginIfMapEquals(HValue* value, Handle<Map> map);
+ void BeginElse();
void End();
private:
@@ -965,6 +986,7 @@ class HGraphBuilder {
HGraphBuilder* builder_;
bool finished_;
+ bool did_else_;
HBasicBlock* first_true_block_;
HBasicBlock* last_true_block_;
HBasicBlock* first_false_block_;
@@ -983,8 +1005,7 @@ class HGraphBuilder {
LoopBuilder(HGraphBuilder* builder,
HValue* context,
- Direction direction,
- BailoutId id);
+ Direction direction);
~LoopBuilder() {
ASSERT(finished_);
}
@@ -1011,16 +1032,35 @@ class HGraphBuilder {
bool finished_;
};
- HValue* BuildAllocateElements(HContext* context,
+ HValue* BuildNewElementsCapacity(HValue* context,
+ HValue* old_capacity);
+
+ void BuildNewSpaceArrayCheck(HValue* length,
+ ElementsKind kind);
+
+ HValue* BuildAllocateElements(HValue* context,
ElementsKind kind,
HValue* capacity);
- void BuildCopyElements(HContext* context,
+ HValue* BuildGrowElementsCapacity(HValue* object,
+ HValue* elements,
+ ElementsKind kind,
+ HValue* length,
+ HValue* new_capacity);
+
+ void BuildFillElementsWithHole(HValue* context,
+ HValue* elements,
+ ElementsKind elements_kind,
+ HValue* from,
+ HValue* to);
+
+ void BuildCopyElements(HValue* context,
HValue* from_elements,
ElementsKind from_elements_kind,
HValue* to_elements,
ElementsKind to_elements_kind,
- HValue* length);
+ HValue* length,
+ HValue* capacity);
private:
HGraphBuilder();
@@ -1311,6 +1351,10 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
HValue* object,
SmallMapList* types,
Handle<String> name);
+ bool HandlePolymorphicArrayLengthLoad(Property* expr,
+ HValue* object,
+ SmallMapList* types,
+ Handle<String> name);
void HandlePolymorphicStoreNamedField(Assignment* expr,
HValue* object,
HValue* value,
@@ -1348,7 +1392,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
HValue* val,
HValue* dependency,
Handle<Map> map,
- bool is_store);
+ bool is_store,
+ KeyedAccessStoreMode store_mode);
HValue* HandlePolymorphicElementAccess(HValue* object,
HValue* key,
@@ -1357,6 +1402,7 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
BailoutId ast_id,
int position,
bool is_store,
+ KeyedAccessStoreMode store_mode,
bool* has_side_effects);
HValue* HandleKeyedElementAccess(HValue* obj,
@@ -1383,6 +1429,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
Property* expr,
Handle<Map> map);
+ void AddCheckMap(HValue* object, Handle<Map> map);
+
void AddCheckMapsWithTransitions(HValue* object,
Handle<Map> map);
diff --git a/deps/v8/src/ia32/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc
index afb1c030e..e861db3ac 100644
--- a/deps/v8/src/ia32/builtins-ia32.cc
+++ b/deps/v8/src/ia32/builtins-ia32.cc
@@ -216,8 +216,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// eax: initial map
__ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
__ shl(edi, kPointerSizeLog2);
- __ AllocateInNewSpace(
- edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
+ __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields.
// eax: initial map
// ebx: JSObject
@@ -280,15 +279,15 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// ebx: JSObject
// edi: start of next object (will be start of FixedArray)
// edx: number of elements in properties array
- __ AllocateInNewSpace(FixedArray::kHeaderSize,
- times_pointer_size,
- edx,
- REGISTER_VALUE_IS_INT32,
- edi,
- ecx,
- no_reg,
- &undo_allocation,
- RESULT_CONTAINS_TOP);
+ __ Allocate(FixedArray::kHeaderSize,
+ times_pointer_size,
+ edx,
+ REGISTER_VALUE_IS_INT32,
+ edi,
+ ecx,
+ no_reg,
+ &undo_allocation,
+ RESULT_CONTAINS_TOP);
// Initialize the FixedArray.
// ebx: JSObject
@@ -409,10 +408,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &exit);
- // Symbols are "objects".
- __ CmpInstanceType(ecx, SYMBOL_TYPE);
- __ j(equal, &exit);
-
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ bind(&use_receiver);
@@ -1129,15 +1124,15 @@ static void AllocateJSArray(MacroAssembler* masm,
// Allocate the JSArray object together with space for a FixedArray with the
// requested elements.
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
- __ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
- times_pointer_size,
- array_size,
- REGISTER_VALUE_IS_SMI,
- result,
- elements_array_end,
- scratch,
- gc_required,
- TAG_OBJECT);
+ __ Allocate(JSArray::kSize + FixedArray::kHeaderSize,
+ times_pointer_size,
+ array_size,
+ REGISTER_VALUE_IS_SMI,
+ result,
+ elements_array_end,
+ scratch,
+ gc_required,
+ TAG_OBJECT);
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc
index 88207c490..9b77c50c0 100644
--- a/deps/v8/src/ia32/code-stubs-ia32.cc
+++ b/deps/v8/src/ia32/code-stubs-ia32.cc
@@ -67,6 +67,17 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
}
+void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { edx, ecx, eax };
+ descriptor->register_param_count_ = 3;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure);
+}
+
+
void TransitionElementsKindStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -89,7 +100,7 @@ static void InitializeArrayConstructorDescriptor(Isolate* isolate,
// stack param count needs (constructor pointer, and single argument)
descriptor->stack_parameter_count_ = &eax;
descriptor->register_params_ = registers;
- descriptor->extra_expression_stack_count_ = 1;
+ descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
descriptor->deoptimization_handler_ =
FUNCTION_ADDR(ArrayConstructor_StubFailure);
}
@@ -621,6 +632,14 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ bind(&not_string);
}
+ if (types_.Contains(SYMBOL)) {
+ // Symbol value -> true.
+ Label not_symbol;
+ __ CmpInstanceType(map, SYMBOL_TYPE);
+ __ j(not_equal, &not_symbol, Label::kNear);
+ __ bind(&not_symbol);
+ }
+
if (types_.Contains(HEAP_NUMBER)) {
// heap number -> false iff +0, -0, or NaN.
Label not_heap_number, false_result;
@@ -3285,25 +3304,6 @@ void MathPowStub::Generate(MacroAssembler* masm) {
}
-void ArrayLengthStub::Generate(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- if (kind() == Code::KEYED_LOAD_IC) {
- __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
- __ j(not_equal, &miss);
- }
-
- StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss);
- __ bind(&miss);
- StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
-}
-
-
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ecx : name
@@ -3558,7 +3558,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
__ add(ebx, Immediate(Heap::kArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ AllocateInNewSpace(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
+ __ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
// eax = address of new object(s) (tagged)
// ecx = argument count (tagged)
@@ -3756,7 +3756,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
__ add(ecx, Immediate(Heap::kArgumentsObjectSizeStrict));
// Do the allocation of both objects in one go.
- __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
+ __ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
// Get the arguments boilerplate from the current native context.
__ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
@@ -4280,15 +4280,15 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
// Allocate RegExpResult followed by FixedArray with size in ebx.
// JSArray: [Map][empty properties][Elements][Length-smi][index][input]
// Elements: [Map][Length][..elements..]
- __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize,
- times_pointer_size,
- ebx, // In: Number of elements as a smi
- REGISTER_VALUE_IS_SMI,
- eax, // Out: Start of allocation (tagged).
- ecx, // Out: End of allocation.
- edx, // Scratch register
- &slowcase,
- TAG_OBJECT);
+ __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize,
+ times_pointer_size,
+ ebx, // In: Number of elements as a smi
+ REGISTER_VALUE_IS_SMI,
+ eax, // Out: Start of allocation (tagged).
+ ecx, // Out: End of allocation.
+ edx, // Scratch register
+ &slowcase,
+ TAG_OBJECT);
// eax: Start of allocated area, object-tagged.
// Set JSArray map to global.regexp_result_map().
@@ -4525,6 +4525,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
// Identical objects can be compared fast, but there are some tricky cases
// for NaN and undefined.
+ Label generic_heap_number_comparison;
{
Label not_identical;
__ cmp(eax, edx);
@@ -4541,12 +4542,11 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
__ bind(&check_for_nan);
}
- // Test for NaN. Sadly, we can't just compare to factory->nan_value(),
- // so we do the second best thing - test it ourselves.
- Label heap_number;
+ // Test for NaN. Compare heap numbers in a general way,
+ // to hanlde NaNs correctly.
__ cmp(FieldOperand(edx, HeapObject::kMapOffset),
Immediate(masm->isolate()->factory()->heap_number_map()));
- __ j(equal, &heap_number, Label::kNear);
+ __ j(equal, &generic_heap_number_comparison, Label::kNear);
if (cc != equal) {
// Call runtime on identical JSObjects. Otherwise return equal.
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
@@ -4555,37 +4555,6 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
__ Set(eax, Immediate(Smi::FromInt(EQUAL)));
__ ret(0);
- __ bind(&heap_number);
- // It is a heap number, so return non-equal if it's NaN and equal if
- // it's not NaN.
- // The representation of NaN values has all exponent bits (52..62) set,
- // and not all mantissa bits (0..51) clear.
- // We only accept QNaNs, which have bit 51 set.
- // Read top bits of double representation (second word of value).
-
- // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e.,
- // all bits in the mask are set. We only need to check the word
- // that contains the exponent and high bit of the mantissa.
- STATIC_ASSERT(((kQuietNaNHighBitsMask << 1) & 0x80000000u) != 0);
- __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset));
- __ Set(eax, Immediate(0));
- // Shift value and mask so kQuietNaNHighBitsMask applies to topmost
- // bits.
- __ add(edx, edx);
- __ cmp(edx, kQuietNaNHighBitsMask << 1);
- if (cc == equal) {
- STATIC_ASSERT(EQUAL != 1);
- __ setcc(above_equal, eax);
- __ ret(0);
- } else {
- Label nan;
- __ j(above_equal, &nan, Label::kNear);
- __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
- __ ret(0);
- __ bind(&nan);
- __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
- __ ret(0);
- }
__ bind(&not_identical);
}
@@ -4665,6 +4634,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
// Generate the number comparison code.
Label non_number_comparison;
Label unordered;
+ __ bind(&generic_heap_number_comparison);
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope use_sse2(masm, SSE2);
CpuFeatureScope use_cmov(masm, CMOV);
@@ -7825,8 +7795,10 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
__ mov(ebx, MemOperand(ebp, parameter_count_offset));
masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
__ pop(ecx);
- __ lea(esp, MemOperand(esp, ebx, times_pointer_size,
- extra_expression_stack_count_ * kPointerSize));
+ int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
+ ? kPointerSize
+ : 0;
+ __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset));
__ jmp(ecx); // Return to IC Miss stub, continuation still on stack.
}
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index b3fce81a3..550c83d51 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -450,9 +450,8 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
// edi: length of source FixedArray (smi-tagged)
AllocationFlags flags =
static_cast<AllocationFlags>(TAG_OBJECT | DOUBLE_ALIGNMENT);
- __ AllocateInNewSpace(FixedDoubleArray::kHeaderSize, times_8,
- edi, REGISTER_VALUE_IS_SMI,
- eax, ebx, no_reg, &gc_required, flags);
+ __ Allocate(FixedDoubleArray::kHeaderSize, times_8, edi,
+ REGISTER_VALUE_IS_SMI, eax, ebx, no_reg, &gc_required, flags);
// eax: destination FixedDoubleArray
// edi: number of elements
@@ -589,7 +588,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
// Allocate new FixedArray.
// ebx: length of source FixedDoubleArray (smi-tagged)
__ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
- __ AllocateInNewSpace(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
+ __ Allocate(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
// eax: destination FixedArray
// ebx: number of elements
@@ -952,7 +951,7 @@ void Code::PatchPlatformCodeAge(byte* sequence,
uint32_t young_length;
byte* young_sequence = GetNoCodeAgeSequence(&young_length);
if (age == kNoAge) {
- memcpy(sequence, young_sequence, young_length);
+ CopyBytes(sequence, young_sequence, young_length);
CPU::FlushICache(sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(age, parity);
diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc
index ebc3a2bd5..efbdf1354 100644
--- a/deps/v8/src/ia32/full-codegen-ia32.cc
+++ b/deps/v8/src/ia32/full-codegen-ia32.cc
@@ -2567,7 +2567,6 @@ void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
- // TODO(rossberg): incorporate symbols.
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1);
@@ -2703,28 +2702,6 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
}
-void FullCodeGenerator::EmitIsSymbol(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(eax, if_false);
- __ CmpObjectType(eax, SYMBOL_TYPE, ebx);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1);
@@ -4275,6 +4252,10 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ test_b(FieldOperand(edx, Map::kBitFieldOffset),
1 << Map::kIsUndetectable);
Split(zero, if_true, if_false, fall_through);
+ } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ __ JumpIfSmi(eax, if_false);
+ __ CmpObjectType(eax, SYMBOL_TYPE, edx);
+ Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
__ cmp(eax, isolate()->factory()->true_value());
__ j(equal, if_true);
@@ -4306,10 +4287,6 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ cmp(eax, isolate()->factory()->null_value());
__ j(equal, if_true);
}
- if (FLAG_harmony_symbols) {
- __ CmpObjectType(eax, SYMBOL_TYPE, edx);
- __ j(equal, if_true);
- }
__ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx);
__ j(below, if_false);
__ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc
index 205781b9d..4d23aef15 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc
@@ -1740,13 +1740,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
-void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
- Register result = ToRegister(instr->result());
- Register array = ToRegister(instr->value());
- __ mov(result, FieldOperand(array, JSArray::kLengthOffset));
-}
-
-
void LCodeGen::DoFixedArrayBaseLength(
LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
@@ -2116,6 +2109,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ bind(&not_string);
}
+ if (expected.Contains(ToBooleanStub::SYMBOL)) {
+ // Symbol value -> true.
+ __ CmpInstanceType(map, SYMBOL_TYPE);
+ __ j(equal, true_label);
+ }
+
if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
// heap number -> false iff +0, -0, or NaN.
Label not_heap_number;
@@ -5566,7 +5565,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
- __ AllocateInNewSpace(size, result, temp, no_reg, deferred->entry(), flags);
+ __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
}
__ bind(deferred->exit());
@@ -5979,6 +5978,11 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
1 << Map::kIsUndetectable);
final_branch_condition = zero;
+ } else if (type_name->Equals(heap()->symbol_string())) {
+ __ JumpIfSmi(input, false_label);
+ __ CmpObjectType(input, SYMBOL_TYPE, input);
+ final_branch_condition = equal;
+
} else if (type_name->Equals(heap()->boolean_string())) {
__ cmp(input, factory()->true_value());
__ j(equal, true_label);
@@ -6013,13 +6017,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ cmp(input, factory()->null_value());
__ j(equal, true_label);
}
- if (FLAG_harmony_symbols) {
- __ CmpObjectType(input, SYMBOL_TYPE, input);
- __ j(equal, true_label);
- __ CmpInstanceType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- } else {
- __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
- }
+ __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
__ j(below, false_label);
__ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
__ j(above, false_label);
diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc
index f2aec9977..102515a91 100644
--- a/deps/v8/src/ia32/lithium-ia32.cc
+++ b/deps/v8/src/ia32/lithium-ia32.cc
@@ -923,6 +923,35 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LInstruction* instr = current->CompileToLithium(this);
if (instr != NULL) {
+#if DEBUG
+ // Make sure that the lithium instruction has either no fixed register
+ // constraints in temps or the result OR no uses that are only used at
+ // start. If this invariant doesn't hold, the register allocator can decide
+ // to insert a split of a range immediately before the instruction due to an
+ // already allocated register needing to be used for the instruction's fixed
+ // register constraint. In this case, The register allocator won't see an
+ // interference between the split child and the use-at-start (it would if
+ // the it was just a plain use), so it is free to move the split child into
+ // the same register that is used for the use-at-start.
+ // See https://code.google.com/p/chromium/issues/detail?id=201590
+ if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
+ int fixed = 0;
+ int used_at_start = 0;
+ for (UseIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->IsUsedAtStart()) ++used_at_start;
+ }
+ if (instr->Output() != NULL) {
+ if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
+ }
+ for (TempIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->HasFixedPolicy()) ++fixed;
+ }
+ ASSERT(fixed == 0 || used_at_start == 0);
+ }
+#endif
+
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -1182,16 +1211,20 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
input);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
} else {
- LOperand* input = UseRegisterAtStart(instr->value());
LOperand* context = UseAny(instr->context()); // Deferred use by MathAbs.
+ LOperand* input = NULL;
if (op == kMathPowHalf) {
+ input = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister();
LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp);
return DefineSameAsFirst(result);
} else if (op == kMathRound) {
+ input = UseRegister(instr->value());
LOperand* temp = FixedTemp(xmm4);
LMathRound* result = new(zone()) LMathRound(context, input, temp);
return AssignEnvironment(DefineAsRegister(result));
+ } else {
+ input = UseRegisterAtStart(instr->value());
}
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
input);
@@ -1716,12 +1749,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
-LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
- LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LJSArrayLength(array));
-}
-
-
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h
index 0e3647407..1c490bb57 100644
--- a/deps/v8/src/ia32/lithium-ia32.h
+++ b/deps/v8/src/ia32/lithium-ia32.h
@@ -114,7 +114,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@@ -1147,19 +1146,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 0> {
};
-class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LJSArrayLength(LOperand* value) {
- inputs_[0] = value;
- }
-
- LOperand* value() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
- DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
-};
-
-
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index debf64aa1..3d3dabca4 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -1332,18 +1332,16 @@ void MacroAssembler::Allocate(int object_size,
}
-void MacroAssembler::AllocateInNewSpace(
- int header_size,
- ScaleFactor element_size,
- Register element_count,
- RegisterValueType element_count_type,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ RegisterValueType element_count_type,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT((flags & SIZE_IN_WORDS) == 0);
- ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1365,6 +1363,7 @@ void MacroAssembler::AllocateInNewSpace(
// Align the next allocation. Storing the filler map without checking top is
// always safe because the limit of the heap is always aligned.
if ((flags & DOUBLE_ALIGNMENT) != 0) {
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
Label aligned;
test(result, Immediate(kDoubleAlignmentMask));
@@ -1375,9 +1374,9 @@ void MacroAssembler::AllocateInNewSpace(
bind(&aligned);
}
- // Calculate new top and bail out if new space is exhausted.
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ // Calculate new top and bail out if space is exhausted.
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
// We assume that element_count*element_size + header_size does not
// overflow.
@@ -1394,7 +1393,7 @@ void MacroAssembler::AllocateInNewSpace(
lea(result_end, Operand(element_count, element_size, header_size));
add(result_end, result);
j(carry, gc_required);
- cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
+ cmp(result_end, Operand::StaticVariable(allocation_limit));
j(above, gc_required);
if ((flags & TAG_OBJECT) != 0) {
@@ -1407,14 +1406,13 @@ void MacroAssembler::AllocateInNewSpace(
}
-void MacroAssembler::AllocateInNewSpace(Register object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(Register object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
- ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1436,6 +1434,7 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
// Align the next allocation. Storing the filler map without checking top is
// always safe because the limit of the heap is always aligned.
if ((flags & DOUBLE_ALIGNMENT) != 0) {
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
Label aligned;
test(result, Immediate(kDoubleAlignmentMask));
@@ -1446,15 +1445,16 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
bind(&aligned);
}
- // Calculate new top and bail out if new space is exhausted.
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ // Calculate new top and bail out if space is exhausted.
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
+
if (!object_size.is(result_end)) {
mov(result_end, object_size);
}
add(result_end, result);
j(carry, gc_required);
- cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
+ cmp(result_end, Operand::StaticVariable(allocation_limit));
j(above, gc_required);
// Tag result if requested.
@@ -1511,15 +1511,15 @@ void MacroAssembler::AllocateTwoByteString(Register result,
and_(scratch1, Immediate(~kObjectAlignmentMask));
// Allocate two byte string in new space.
- AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
- times_1,
- scratch1,
- REGISTER_VALUE_IS_INT32,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(SeqTwoByteString::kHeaderSize,
+ times_1,
+ scratch1,
+ REGISTER_VALUE_IS_INT32,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1547,15 +1547,15 @@ void MacroAssembler::AllocateAsciiString(Register result,
and_(scratch1, Immediate(~kObjectAlignmentMask));
// Allocate ASCII string in new space.
- AllocateInNewSpace(SeqOneByteString::kHeaderSize,
- times_1,
- scratch1,
- REGISTER_VALUE_IS_INT32,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(SeqOneByteString::kHeaderSize,
+ times_1,
+ scratch1,
+ REGISTER_VALUE_IS_INT32,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
mov(FieldOperand(result, HeapObject::kMapOffset),
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h
index 8dd412071..b3dae7320 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.h
+++ b/deps/v8/src/ia32/macro-assembler-ia32.h
@@ -582,22 +582,22 @@ class MacroAssembler: public Assembler {
Label* gc_required,
AllocationFlags flags);
- void AllocateInNewSpace(int header_size,
- ScaleFactor element_size,
- Register element_count,
- RegisterValueType element_count_type,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags);
-
- void AllocateInNewSpace(Register object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ RegisterValueType element_count_type,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
+
+ void Allocate(Register object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
// Undo allocation in new space. The object passed and objects allocated after
// it will no longer be allocated. Make sure that no pointers are left to the
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index f7e795e78..cb4b4a731 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -730,7 +730,7 @@ void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
// but may be destroyed if store is successful.
void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
@@ -740,16 +740,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Register scratch2,
Label* miss_label,
Label* miss_restore_name) {
- LookupResult lookup(masm->isolate());
- object->Lookup(*name, &lookup);
- if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
- // In sloppy mode, we could just return the value and be done. However, we
- // might be in strict mode, where we have to throw. Since we cannot tell,
- // go into slow case unconditionally.
- __ jmp(miss_label);
- return;
- }
-
// Check that the map of the object hasn't changed.
CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
: REQUIRE_EXACT_MAP;
@@ -764,8 +754,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Check that we are allowed to write this.
if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
JSObject* holder;
- if (lookup.IsFound()) {
- holder = lookup.holder();
+ // holder == object indicates that no property was found.
+ if (lookup->holder() != *object) {
+ holder = lookup->holder();
} else {
// Find the top object.
holder = *object;
@@ -774,8 +765,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
} while (holder->GetPrototype()->IsJSObject());
}
// We need an extra register, push
- CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, miss_restore_name);
+ Register holder_reg = CheckPrototypes(
+ object, receiver_reg, Handle<JSObject>(holder), name_reg,
+ scratch1, scratch2, name, miss_restore_name);
+ // If no property was found, and the holder (the last object in the
+ // prototype chain) is in slow mode, we need to do a negative lookup on the
+ // holder.
+ if (lookup->holder() == *object &&
+ !holder->HasFastProperties() &&
+ !holder->IsJSGlobalProxy() &&
+ !holder->IsJSGlobalObject()) {
+ GenerateDictionaryNegativeLookup(
+ masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
+ }
}
// Stub never generated for non-global objects that require access
@@ -799,6 +801,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
return;
}
+ int index;
if (!transition.is_null()) {
// Update the map of the object.
__ mov(scratch1, Immediate(transition));
@@ -813,8 +816,13 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kDontSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
+ index = transition->instance_descriptors()->GetFieldIndex(
+ transition->LastAdded());
+ } else {
+ index = lookup->GetFieldIndex().field_index();
}
+
// Adjust for the number of properties stored in the object. Even in the
// face of a transition we can use the old map here because the size of the
// object and the number of in-object properties is not going to change.
@@ -2350,6 +2358,12 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
// Check that the object is a symbol.
__ CmpObjectType(edx, SYMBOL_TYPE, eax);
__ j(not_equal, &miss);
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss);
+ CheckPrototypes(
+ Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
+ eax, holder, ebx, edx, edi, name, &miss);
break;
case NUMBER_CHECK: {
diff --git a/deps/v8/src/ic-inl.h b/deps/v8/src/ic-inl.h
index 9439792be..ca02183db 100644
--- a/deps/v8/src/ic-inl.h
+++ b/deps/v8/src/ic-inl.h
@@ -109,7 +109,7 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object,
// If the object is a value, we use the prototype map for the cache.
ASSERT(object->IsString() || object->IsSymbol() ||
object->IsNumber() || object->IsBoolean());
- return DELEGATE_MAP;
+ return PROTOTYPE_MAP;
}
@@ -124,7 +124,7 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(JSObject* object,
!object->HasFastProperties() &&
!object->IsJSGlobalProxy() &&
!object->IsJSGlobalObject()) {
- return DELEGATE_MAP;
+ return PROTOTYPE_MAP;
}
return OWN_MAP;
}
@@ -133,7 +133,8 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(JSObject* object,
JSObject* IC::GetCodeCacheHolder(Isolate* isolate,
Object* object,
InlineCacheHolderFlag holder) {
- Object* map_owner = holder == OWN_MAP ? object : object->GetDelegate(isolate);
+ Object* map_owner =
+ holder == OWN_MAP ? object : object->GetPrototype(isolate);
ASSERT(map_owner->IsJSObject());
return JSObject::cast(map_owner);
}
diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc
index da2211b7b..515c6f71a 100644
--- a/deps/v8/src/ic.cc
+++ b/deps/v8/src/ic.cc
@@ -160,7 +160,7 @@ Address IC::OriginalCodeAddress() const {
// Find the function on the stack and both the active code for the
// function and the original code.
JSFunction* function = JSFunction::cast(frame->function());
- Handle<SharedFunctionInfo> shared(function->shared());
+ Handle<SharedFunctionInfo> shared(function->shared(), isolate());
Code* code = shared->code();
ASSERT(Debug::HasDebugInfo(shared));
Code* original_code = Debug::GetDebugInfo(shared)->original_code();
@@ -190,7 +190,7 @@ static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
// The stub was generated for JSObject but called for non-JSObject.
// IC::GetCodeCacheHolder is not applicable.
return false;
- } else if (cache_holder == DELEGATE_MAP &&
+ } else if (cache_holder == PROTOTYPE_MAP &&
receiver->GetPrototype(isolate)->IsNull()) {
// IC::GetCodeCacheHolder is not applicable.
return false;
@@ -435,7 +435,7 @@ static void LookupForRead(Handle<Object> object,
return;
}
- Handle<JSObject> holder(lookup->holder());
+ Handle<JSObject> holder(lookup->holder(), lookup->isolate());
if (HasInterceptorGetter(*holder)) {
return;
}
@@ -446,7 +446,7 @@ static void LookupForRead(Handle<Object> object,
return;
}
- Handle<Object> proto(holder->GetPrototype(), name->GetIsolate());
+ Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
if (proto->IsNull()) {
ASSERT(!lookup->IsFound());
return;
@@ -636,7 +636,7 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
Handle<Object> object,
Handle<String> name) {
int argc = target()->arguments_count();
- Handle<JSObject> holder(lookup->holder());
+ Handle<JSObject> holder(lookup->holder(), isolate());
switch (lookup->type()) {
case FIELD: {
PropertyIndex index = lookup->GetFieldIndex();
@@ -647,7 +647,7 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
// Get the constant function and compute the code stub for this
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
- Handle<JSFunction> function(lookup->GetConstantFunction());
+ Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
return isolate()->stub_cache()->ComputeCallConstant(
argc, kind_, extra_state, name, object, holder, function);
}
@@ -658,7 +658,8 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
if (holder->IsGlobalObject()) {
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
+ Handle<JSGlobalPropertyCell> cell(
+ global->GetPropertyCell(lookup), isolate());
if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
Handle<JSFunction> function(JSFunction::cast(cell->value()));
return isolate()->stub_cache()->ComputeCallGlobal(
@@ -746,7 +747,8 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
// GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
Handle<JSObject> cache_object = object->IsJSObject()
? Handle<JSObject>::cast(object)
- : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())));
+ : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
+ isolate());
// Update the stub cache.
UpdateMegamorphicCache(cache_object->map(), *name, *code);
break;
@@ -855,28 +857,6 @@ MaybeObject* LoadIC::Load(State state,
return Smi::FromInt(String::cast(*string)->length());
}
- // Use specialized code for getting the length of arrays.
- if (object->IsJSArray() &&
- name->Equals(isolate()->heap()->length_string())) {
- Handle<Code> stub;
- if (state == UNINITIALIZED) {
- stub = pre_monomorphic_stub();
- } else if (state == PREMONOMORPHIC) {
- ArrayLengthStub array_length_stub(kind());
- stub = array_length_stub.GetCode(isolate());
- } else if (state != MEGAMORPHIC) {
- ASSERT(state != GENERIC);
- stub = megamorphic_stub();
- }
- if (!stub.is_null()) {
- set_target(*stub);
-#ifdef DEBUG
- if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
-#endif
- }
- return JSArray::cast(*object)->length();
- }
-
// Use specialized code for getting prototype of functions.
if (object->IsJSFunction() &&
name->Equals(isolate()->heap()->prototype_string()) &&
@@ -1035,6 +1015,22 @@ void IC::CopyICToMegamorphicCache(Handle<String> name) {
}
+bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
+ AssertNoAllocation no_allocation;
+
+ Map* current_map = target()->FindFirstMap();
+ ElementsKind receiver_elements_kind = receiver_map->elements_kind();
+ bool more_general_transition =
+ IsMoreGeneralElementsKindTransition(
+ current_map->elements_kind(), receiver_elements_kind);
+ Map* transitioned_map = more_general_transition
+ ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
+ : NULL;
+
+ return transitioned_map == receiver_map;
+}
+
+
// Since GC may have been invoked, by the time PatchCache is called, |state| is
// not necessarily equal to target()->state().
void IC::PatchCache(State state,
@@ -1052,6 +1048,17 @@ void IC::PatchCache(State state,
// Only move to megamorphic if the target changes.
if (target() != *code) {
if (target()->is_load_stub()) {
+ bool is_same_handler = false;
+ {
+ AssertNoAllocation no_allocation;
+ Code* old_handler = target()->FindFirstCode();
+ is_same_handler = old_handler == *code;
+ }
+ if (is_same_handler
+ && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
+ UpdateMonomorphicIC(receiver, code, name);
+ break;
+ }
if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
break;
}
@@ -1196,7 +1203,8 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
case NORMAL:
if (holder->IsGlobalObject()) {
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
+ Handle<JSGlobalPropertyCell> cell(
+ global->GetPropertyCell(lookup), isolate());
return isolate()->stub_cache()->ComputeLoadGlobal(
name, receiver, global, cell, lookup->IsDontDelete());
}
@@ -1223,6 +1231,12 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
if (!holder->HasFastProperties()) break;
return isolate()->stub_cache()->ComputeLoadViaGetter(
name, receiver, holder, Handle<JSFunction>::cast(getter));
+ } else if (receiver->IsJSArray() &&
+ name->Equals(isolate()->heap()->length_string())) {
+ PropertyIndex lengthIndex =
+ PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize);
+ return isolate()->stub_cache()->ComputeLoadField(
+ name, receiver, holder, lengthIndex);
}
// TODO(dcarney): Handle correctly.
if (callback->IsDeclaredAccessorInfo()) break;
@@ -1272,7 +1286,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
return generic_stub();
}
- Handle<Map> receiver_map(receiver->map());
+ Handle<Map> receiver_map(receiver->map(), isolate());
MapHandleList target_receiver_maps;
if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
// Optimistically assume that ICs that haven't reached the MONOMORPHIC state
@@ -1283,7 +1297,8 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
if (target() == *string_stub()) {
target_receiver_maps.Add(isolate()->factory()->string_map());
} else {
- GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
+ GetReceiverMapsForStub(Handle<Code>(target(), isolate()),
+ &target_receiver_maps);
if (target_receiver_maps.length() == 0) {
return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
}
@@ -1355,7 +1370,8 @@ MaybeObject* KeyedLoadIC::Load(State state,
stub = non_strict_arguments_stub();
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
- } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
+ } else if (!key->ToSmi()->IsFailure() &&
+ (target() != *non_strict_arguments_stub())) {
stub = LoadElementStub(receiver);
}
}
@@ -1379,13 +1395,13 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
if (!lookup->IsProperty()) return Handle<Code>::null();
// Compute a monomorphic stub.
- Handle<JSObject> holder(lookup->holder());
+ Handle<JSObject> holder(lookup->holder(), isolate());
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeKeyedLoadField(
name, receiver, holder, lookup->GetFieldIndex());
case CONSTANT_FUNCTION: {
- Handle<JSFunction> constant(lookup->GetConstantFunction());
+ Handle<JSFunction> constant(lookup->GetConstantFunction(), isolate());
return isolate()->stub_cache()->ComputeKeyedLoadConstant(
name, receiver, holder, constant);
}
@@ -1413,41 +1429,42 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
}
-static bool StoreICableLookup(LookupResult* lookup) {
- // Bail out if we didn't find a result.
- if (!lookup->IsFound()) return false;
-
- // Bail out if inline caching is not allowed.
- if (!lookup->IsCacheable()) return false;
-
- // If the property is read-only, we leave the IC in its current state.
- if (lookup->IsTransition()) {
- return !lookup->GetTransitionDetails().IsReadOnly();
- }
- return !lookup->IsReadOnly();
-}
-
-
static bool LookupForWrite(Handle<JSObject> receiver,
Handle<String> name,
LookupResult* lookup) {
- receiver->LocalLookup(*name, lookup);
- if (!lookup->IsFound()) {
- receiver->map()->LookupTransition(*receiver, *name, lookup);
- }
- if (!StoreICableLookup(lookup)) {
- // 2nd chance: There can be accessors somewhere in the prototype chain.
- receiver->Lookup(*name, lookup);
- return lookup->IsPropertyCallbacks() && StoreICableLookup(lookup);
- }
+ Handle<JSObject> holder = receiver;
+ receiver->Lookup(*name, lookup);
+ if (lookup->IsFound()) {
+ if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
+
+ if (lookup->holder() == *receiver) {
+ if (lookup->IsInterceptor() &&
+ receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
+ receiver->LocalLookupRealNamedProperty(*name, lookup);
+ return lookup->IsFound() &&
+ !lookup->IsReadOnly() &&
+ lookup->IsCacheable();
+ }
+ return true;
+ }
- if (lookup->IsInterceptor() &&
- receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
- receiver->LocalLookupRealNamedProperty(*name, lookup);
- return StoreICableLookup(lookup);
+ if (lookup->IsPropertyCallbacks()) return true;
+
+ // Currently normal holders in the prototype chain are not supported. They
+ // would require a runtime positive lookup and verification that the details
+ // have not changed.
+ if (lookup->IsInterceptor() || lookup->IsNormal()) return false;
+ holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
}
- return true;
+ // While normally LookupTransition gets passed the receiver, in this case we
+ // pass the holder of the property that we overwrite. This keeps the holder in
+ // the LookupResult intact so we can later use it to generate a prototype
+ // chain check. This avoids a double lookup, but requires us to pass in the
+ // receiver when trying to fetch extra information from the transition.
+ receiver->map()->LookupTransition(*holder, *name, lookup);
+ return lookup->IsTransition() &&
+ !lookup->GetTransitionDetails(receiver->map()).IsReadOnly();
}
@@ -1547,7 +1564,6 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
Handle<String> name,
Handle<Object> value) {
ASSERT(!receiver->IsJSGlobalProxy());
- ASSERT(StoreICableLookup(lookup));
ASSERT(lookup->IsFound());
// These are not cacheable, so we never see such LookupResults here.
@@ -1570,19 +1586,19 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeStoreField(
- name, receiver, lookup->GetFieldIndex().field_index(),
- Handle<Map>::null(), strict_mode);
+ name, receiver, lookup, Handle<Map>::null(), strict_mode);
case NORMAL:
if (receiver->IsGlobalObject()) {
// The stub generated for the global object picks the value directly
// from the property cell. So the property must be directly on the
// global object.
Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
+ Handle<JSGlobalPropertyCell> cell(
+ global->GetPropertyCell(lookup), isolate());
return isolate()->stub_cache()->ComputeStoreGlobal(
name, global, cell, strict_mode);
}
- if (!holder.is_identical_to(receiver)) break;
+ ASSERT(holder.is_identical_to(receiver));
return isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
case CALLBACKS: {
Handle<Object> callback(lookup->GetCallbackObject(), isolate());
@@ -1595,8 +1611,8 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
return isolate()->stub_cache()->ComputeStoreCallback(
name, receiver, holder, info, strict_mode);
} else if (callback->IsAccessorPair()) {
- Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter(),
- isolate());
+ Handle<Object> setter(
+ Handle<AccessorPair>::cast(callback)->setter(), isolate());
if (!setter->IsJSFunction()) break;
if (holder->IsGlobalObject()) break;
if (!holder->HasFastProperties()) break;
@@ -1617,7 +1633,10 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
case CONSTANT_FUNCTION:
break;
case TRANSITION: {
- Handle<Map> transition(lookup->GetTransitionTarget());
+ // Explicitly pass in the receiver map since LookupForWrite may have
+ // stored something else than the receiver in the holder.
+ Handle<Map> transition(
+ lookup->GetTransitionTarget(receiver->map()), isolate());
int descriptor = transition->LastAdded();
DescriptorArray* target_descriptors = transition->instance_descriptors();
@@ -1625,9 +1644,8 @@ Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
if (details.type() != FIELD || details.attributes() != NONE) break;
- int field_index = target_descriptors->GetFieldIndex(descriptor);
return isolate()->stub_cache()->ComputeStoreField(
- name, receiver, field_index, transition, strict_mode);
+ name, receiver, lookup, transition, strict_mode);
}
case NONEXISTENT:
case HANDLER:
@@ -1649,7 +1667,8 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
}
- if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
+ if (!FLAG_compiled_keyed_stores &&
+ (store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS)) {
// TODO(danno): We'll soon handle MONOMORPHIC ICs that also support
// copying COW arrays and silently ignoring some OOB stores into external
@@ -1661,7 +1680,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
}
State ic_state = target()->ic_state();
- Handle<Map> receiver_map(receiver->map());
+ Handle<Map> receiver_map(receiver->map(), isolate());
if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
// Optimistically assume that ICs that haven't reached the MONOMORPHIC state
// yet will do so and stay there.
@@ -1697,24 +1716,18 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
transitioned_receiver_map =
ComputeTransitionedMap(receiver, store_mode);
}
- ElementsKind transitioned_kind =
- transitioned_receiver_map->elements_kind();
- bool more_general_transition =
- IsMoreGeneralElementsKindTransition(
- previous_receiver_map->elements_kind(),
- transitioned_kind);
- Map* transitioned_previous_map = more_general_transition
- ? previous_receiver_map->LookupElementsTransitionMap(transitioned_kind)
- : NULL;
- if (transitioned_previous_map == *transitioned_receiver_map) {
+ if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) {
// Element family is the same, use the "worst" case map.
store_mode = GetNonTransitioningStoreMode(store_mode);
return isolate()->stub_cache()->ComputeKeyedStoreElement(
transitioned_receiver_map, strict_mode, store_mode);
} else if (*previous_receiver_map == receiver->map()) {
- if (IsGrowStoreMode(store_mode)) {
+ if (IsGrowStoreMode(store_mode) ||
+ store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
+ store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
// A "normal" IC that handles stores can switch to a version that can
- // grow at the end of the array and still stay MONOMORPHIC.
+ // grow at the end of the array, handle OOB accesses or copy COW arrays
+ // and still stay MONOMORPHIC.
return isolate()->stub_cache()->ComputeKeyedStoreElement(
receiver_map, strict_mode, store_mode);
}
@@ -1761,6 +1774,26 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
}
}
+ // If the store mode isn't the standard mode, make sure that all polymorphic
+ // receivers are either external arrays, or all "normal" arrays. Otherwise,
+ // use the generic stub.
+ if (store_mode != STANDARD_STORE) {
+ int external_arrays = 0;
+ for (int i = 0; i < target_receiver_maps.length(); ++i) {
+ if (target_receiver_maps[i]->has_external_array_elements()) {
+ external_arrays++;
+ }
+ }
+ if (external_arrays != 0 &&
+ external_arrays != target_receiver_maps.length()) {
+ TRACE_GENERIC_IC(isolate(), "KeyedIC",
+ "unsupported combination of external and normal arrays");
+ return strict_mode == kStrictMode
+ ? generic_stub_strict()
+ : generic_stub();
+ }
+ }
+
return isolate()->stub_cache()->ComputeStoreElementPolymorphic(
&target_receiver_maps, store_mode, strict_mode);
}
@@ -1794,7 +1827,7 @@ Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
case STORE_NO_TRANSITION_HANDLE_COW:
case STANDARD_STORE:
case STORE_AND_GROW_NO_TRANSITION:
- return Handle<Map>(receiver->map());
+ return Handle<Map>(receiver->map(), isolate());
}
return Handle<Map>::null();
}
@@ -1813,8 +1846,10 @@ bool IsOutOfBoundsAccess(Handle<JSObject> receiver,
KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
Handle<Object> key,
Handle<Object> value) {
- ASSERT(key->IsSmi());
- int index = Smi::cast(*key)->value();
+ ASSERT(!key->ToSmi()->IsFailure());
+ Smi* smi_key = NULL;
+ key->ToSmi()->To(&smi_key);
+ int index = smi_key->value();
bool oob_access = IsOutOfBoundsAccess(receiver, index);
bool allow_growth = receiver->IsJSArray() && oob_access;
if (allow_growth) {
@@ -1872,6 +1907,10 @@ KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
if (!FLAG_trace_external_array_abuse &&
receiver->map()->has_external_array_elements() && oob_access) {
return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
+ }
+ Heap* heap = receiver->GetHeap();
+ if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
+ return STORE_NO_TRANSITION_HANDLE_COW;
} else {
return STANDARD_STORE;
}
@@ -1910,13 +1949,20 @@ MaybeObject* KeyedStoreIC::Store(State state,
if (miss_mode != MISS_FORCE_GENERIC) {
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+ bool key_is_smi_like = key->IsSmi() ||
+ (FLAG_compiled_keyed_stores && !key->ToSmi()->IsFailure());
if (receiver->elements()->map() ==
isolate()->heap()->non_strict_arguments_elements_map()) {
stub = non_strict_arguments_stub();
- } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
+ } else if (key_is_smi_like &&
+ (target() != *non_strict_arguments_stub())) {
KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
stub = StoreElementStub(receiver, store_mode, strict_mode);
+ } else {
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number");
}
+ } else {
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object");
}
} else {
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic");
@@ -1941,19 +1987,20 @@ Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
switch (lookup->type()) {
case FIELD:
return isolate()->stub_cache()->ComputeKeyedStoreField(
- name, receiver, lookup->GetFieldIndex().field_index(),
- Handle<Map>::null(), strict_mode);
+ name, receiver, lookup, Handle<Map>::null(), strict_mode);
case TRANSITION: {
- Handle<Map> transition(lookup->GetTransitionTarget());
+ // Explicitly pass in the receiver map since LookupForWrite may have
+ // stored something else than the receiver in the holder.
+ Handle<Map> transition(
+ lookup->GetTransitionTarget(receiver->map()), isolate());
int descriptor = transition->LastAdded();
DescriptorArray* target_descriptors = transition->instance_descriptors();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() == FIELD && details.attributes() == NONE) {
- int field_index = target_descriptors->GetFieldIndex(descriptor);
return isolate()->stub_cache()->ComputeKeyedStoreField(
- name, receiver, field_index, transition, strict_mode);
+ name, receiver, lookup, transition, strict_mode);
}
// fall through.
}
@@ -2023,7 +2070,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
if (raw_function->is_compiled()) return raw_function;
- Handle<JSFunction> function(raw_function);
+ Handle<JSFunction> function(raw_function, isolate);
JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
return *function;
}
@@ -2074,7 +2121,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- StoreIC ic(isolate);
+ StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
return ic.Store(state,
@@ -2150,7 +2197,22 @@ RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- KeyedStoreIC ic(isolate);
+ KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
+ IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
+ Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
+ return ic.Store(state,
+ Code::GetStrictMode(extra_ic_state),
+ args.at<Object>(0),
+ args.at<Object>(1),
+ args.at<Object>(2),
+ MISS);
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
+ KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
return ic.Store(state,
@@ -2165,7 +2227,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
NoHandleAllocation na(isolate);
ASSERT(args.length() == 3);
- KeyedStoreIC ic(isolate);
+ KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
Handle<Object> object = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1);
@@ -2183,7 +2245,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- KeyedStoreIC ic(isolate);
+ KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
return ic.Store(state,
@@ -2668,7 +2730,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
HasInlinedSmiCode(address()), x, y);
ICCompareStub stub(op_, new_left, new_right, state);
if (state == KNOWN_OBJECT) {
- stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
+ stub.set_known_map(
+ Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
}
set_target(*stub.GetCode(isolate()));
diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h
index b22595552..55b566192 100644
--- a/deps/v8/src/ic.h
+++ b/deps/v8/src/ic.h
@@ -176,6 +176,7 @@ class IC {
Handle<String> name,
Handle<Code> code);
void CopyICToMegamorphicCache(Handle<String> name);
+ bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
void PatchCache(State state,
StrictModeFlag strict_mode,
Handle<JSObject> receiver,
@@ -496,7 +497,7 @@ class KeyedLoadIC: public LoadIC {
class StoreIC: public IC {
public:
- explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
+ StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
ASSERT(target()->is_store_stub() || target()->is_keyed_store_stub());
}
@@ -585,7 +586,8 @@ enum KeyedStoreIncrementLength {
class KeyedStoreIC: public StoreIC {
public:
- explicit KeyedStoreIC(Isolate* isolate) : StoreIC(isolate) {
+ KeyedStoreIC(FrameDepth depth, Isolate* isolate)
+ : StoreIC(depth, isolate) {
ASSERT(target()->is_keyed_store_stub());
}
@@ -786,6 +788,7 @@ enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
} } // namespace v8::internal
diff --git a/deps/v8/src/interpreter-irregexp.cc b/deps/v8/src/interpreter-irregexp.cc
index 5abeb5a10..e678e6cf1 100644
--- a/deps/v8/src/interpreter-irregexp.cc
+++ b/deps/v8/src/interpreter-irregexp.cc
@@ -73,9 +73,15 @@ static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
unsigned int old_char = subject[from++];
unsigned int new_char = subject[current++];
if (old_char == new_char) continue;
- if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20;
- if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20;
+ // Convert both characters to lower case.
+ old_char |= 0x20;
+ new_char |= 0x20;
if (old_char != new_char) return false;
+ // Not letters in the ASCII range and Latin-1 range.
+ if (!(old_char - 'a' <= 'z' - 'a') &&
+ !(old_char - 224 <= 254 - 224 && old_char != 247)) {
+ return false;
+ }
}
return true;
}
diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc
index 5d4bc89b9..04155195a 100644
--- a/deps/v8/src/isolate.cc
+++ b/deps/v8/src/isolate.cc
@@ -612,13 +612,16 @@ Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
limit = Max(limit, 0); // Ensure that limit is not negative.
int initial_size = Min(limit, 10);
Handle<FixedArray> elements =
- factory()->NewFixedArrayWithHoles(initial_size * 4);
+ factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
// If the caller parameter is a function we skip frames until we're
// under it before starting to collect.
bool seen_caller = !caller->IsJSFunction();
- int cursor = 0;
+ // First element is reserved to store the number of non-strict frames.
+ int cursor = 1;
int frames_seen = 0;
+ int non_strict_frames = 0;
+ bool encountered_strict_function = false;
for (StackFrameIterator iter(this);
!iter.done() && frames_seen < limit;
iter.Advance()) {
@@ -646,6 +649,17 @@ Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
Handle<JSFunction> fun = frames[i].function();
Handle<Code> code = frames[i].code();
Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
+ // The stack trace API should not expose receivers and function
+ // objects on frames deeper than the top-most one with a strict
+ // mode function. The number of non-strict frames is stored as
+ // first element in the result array.
+ if (!encountered_strict_function) {
+ if (!fun->shared()->is_classic_mode()) {
+ encountered_strict_function = true;
+ } else {
+ non_strict_frames++;
+ }
+ }
elements->set(cursor++, *recv);
elements->set(cursor++, *fun);
elements->set(cursor++, *code);
@@ -653,6 +667,7 @@ Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
}
}
}
+ elements->set(0, Smi::FromInt(non_strict_frames));
Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
result->set_length(Smi::FromInt(cursor));
return result;
@@ -1679,6 +1694,7 @@ Isolate::Isolate()
code_stub_interface_descriptors_(NULL),
context_exit_happened_(false),
cpu_profiler_(NULL),
+ heap_profiler_(NULL),
deferred_handles_head_(NULL),
optimizing_compiler_thread_(this),
marking_thread_(NULL),
@@ -1810,7 +1826,8 @@ void Isolate::Deinit() {
preallocated_message_space_ = NULL;
PreallocatedMemoryThreadStop();
- HeapProfiler::TearDown();
+ delete heap_profiler_;
+ heap_profiler_ = NULL;
delete cpu_profiler_;
cpu_profiler_ = NULL;
@@ -2043,7 +2060,7 @@ bool Isolate::Init(Deserializer* des) {
logger_->SetUp();
cpu_profiler_ = new CpuProfiler(this);
- HeapProfiler::SetUp();
+ heap_profiler_ = new HeapProfiler(heap());
// Initialize other runtime facilities
#if defined(USE_SIMULATOR)
diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h
index ad0b260bc..f7a81d30d 100644
--- a/deps/v8/src/isolate.h
+++ b/deps/v8/src/isolate.h
@@ -368,7 +368,6 @@ typedef List<HeapObject*, PreallocatedStorageAllocationPolicy> DebugObjectCache;
V(unsigned, ast_node_count, 0) \
/* SafeStackFrameIterator activations count. */ \
V(int, safe_stack_iterator_counter, 0) \
- V(HeapProfiler*, heap_profiler, NULL) \
V(bool, observer_delivery_pending, false) \
V(HStatistics*, hstatistics, NULL) \
V(HTracer*, htracer, NULL) \
@@ -976,6 +975,7 @@ class Isolate {
inline bool DebuggerHasBreakPoints();
CpuProfiler* cpu_profiler() const { return cpu_profiler_; }
+ HeapProfiler* heap_profiler() const { return heap_profiler_; }
#ifdef DEBUG
HistogramInfo* heap_histograms() { return heap_histograms_; }
@@ -1313,6 +1313,7 @@ class Isolate {
Debug* debug_;
#endif
CpuProfiler* cpu_profiler_;
+ HeapProfiler* heap_profiler_;
#define GLOBAL_BACKING_STORE(type, name, initialvalue) \
type name##_;
diff --git a/deps/v8/src/json-parser.h b/deps/v8/src/json-parser.h
index 28ef8b33c..ac34c59b2 100644
--- a/deps/v8/src/json-parser.h
+++ b/deps/v8/src/json-parser.h
@@ -291,6 +291,7 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
// Parse a JSON object. Position must be right at '{'.
template <bool seq_ascii>
Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
+ HandleScope scope(isolate());
Handle<JSObject> json_object =
factory()->NewJSObject(object_constructor(), pretenure_);
ASSERT_EQ(c0_, '{');
@@ -358,12 +359,13 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
}
}
AdvanceSkipWhitespace();
- return json_object;
+ return scope.CloseAndEscape(json_object);
}
// Parse a JSON array. Position must be right at '['.
template <bool seq_ascii>
Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
+ HandleScope scope(isolate());
ZoneScope zone_scope(zone(), DELETE_ON_EXIT);
ZoneList<Handle<Object> > elements(4, zone());
ASSERT_EQ(c0_, '[');
@@ -386,8 +388,9 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
for (int i = 0, n = elements.length(); i < n; i++) {
fast_elements->set(i, *elements[i]);
}
- return factory()->NewJSArrayWithElements(
+ Handle<Object> json_array = factory()->NewJSArrayWithElements(
fast_elements, FAST_ELEMENTS, pretenure_);
+ return scope.CloseAndEscape(json_array);
}
@@ -501,10 +504,10 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
int count = end - start;
int max_length = count + source_length_ - position_;
int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
- Handle<StringType> seq_str =
+ Handle<StringType> seq_string =
NewRawString<StringType>(factory(), length, pretenure_);
// Copy prefix into seq_str.
- SinkChar* dest = seq_str->GetChars();
+ SinkChar* dest = seq_string->GetChars();
String::WriteToFlat(*prefix, dest, start, end);
while (c0_ != '"') {
@@ -512,7 +515,7 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
if (c0_ < 0x20) return Handle<String>::null();
if (count >= length) {
// We need to create a longer sequential string for the result.
- return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
+ return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
}
if (c0_ != '\\') {
// If the sink can contain UC16 characters, or source_ contains only
@@ -522,11 +525,11 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
if (sizeof(SinkChar) == kUC16Size ||
seq_ascii ||
c0_ <= String::kMaxOneByteCharCode) {
- SeqStringSet(seq_str, count++, c0_);
+ SeqStringSet(seq_string, count++, c0_);
Advance();
} else {
// StringType is SeqOneByteString and we just read a non-ASCII char.
- return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str, 0, count);
+ return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
}
} else {
Advance(); // Advance past the \.
@@ -534,22 +537,22 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
case '"':
case '\\':
case '/':
- SeqStringSet(seq_str, count++, c0_);
+ SeqStringSet(seq_string, count++, c0_);
break;
case 'b':
- SeqStringSet(seq_str, count++, '\x08');
+ SeqStringSet(seq_string, count++, '\x08');
break;
case 'f':
- SeqStringSet(seq_str, count++, '\x0c');
+ SeqStringSet(seq_string, count++, '\x0c');
break;
case 'n':
- SeqStringSet(seq_str, count++, '\x0a');
+ SeqStringSet(seq_string, count++, '\x0a');
break;
case 'r':
- SeqStringSet(seq_str, count++, '\x0d');
+ SeqStringSet(seq_string, count++, '\x0d');
break;
case 't':
- SeqStringSet(seq_str, count++, '\x09');
+ SeqStringSet(seq_string, count++, '\x09');
break;
case 'u': {
uc32 value = 0;
@@ -563,13 +566,13 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
}
if (sizeof(SinkChar) == kUC16Size ||
value <= String::kMaxOneByteCharCode) {
- SeqStringSet(seq_str, count++, value);
+ SeqStringSet(seq_string, count++, value);
break;
} else {
// StringType is SeqOneByteString and we just read a non-ASCII char.
position_ -= 6; // Rewind position_ to \ in \uxxxx.
Advance();
- return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str,
+ return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
0,
count);
}
@@ -580,23 +583,13 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
Advance();
}
}
- // Shrink seq_string length to count.
- if (isolate()->heap()->InNewSpace(*seq_str)) {
- isolate()->heap()->new_space()->
- template ShrinkStringAtAllocationBoundary<StringType>(
- *seq_str, count);
- } else {
- int string_size = StringType::SizeFor(count);
- int allocated_string_size = StringType::SizeFor(length);
- int delta = allocated_string_size - string_size;
- Address start_filler_object = seq_str->address() + string_size;
- seq_str->set_length(count);
- isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta);
- }
+
ASSERT_EQ('"', c0_);
// Advance past the last '"'.
AdvanceSkipWhitespace();
- return seq_str;
+
+ // Shrink seq_string length to count and return.
+ return SeqString::Truncate(seq_string, count);
}
@@ -623,8 +616,8 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
int beg_pos = position_;
position_ = position;
return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
- beg_pos,
- position_);
+ beg_pos,
+ position_);
}
if (c0 < 0x20) return Handle<String>::null();
if (static_cast<uint32_t>(c0) >
diff --git a/deps/v8/src/json-stringifier.h b/deps/v8/src/json-stringifier.h
index ad9ef3ddb..bcdd64ce7 100644
--- a/deps/v8/src/json-stringifier.h
+++ b/deps/v8/src/json-stringifier.h
@@ -41,6 +41,9 @@ class BasicJsonStringifier BASE_EMBEDDED {
MaybeObject* Stringify(Handle<Object> object);
+ INLINE(static MaybeObject* StringifyString(Isolate* isolate,
+ Handle<String> object));
+
private:
static const int kInitialPartLength = 32;
static const int kMaxPartLength = 16 * 1024;
@@ -52,7 +55,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
void ChangeEncoding();
- void ShrinkCurrentPart();
+ INLINE(void ShrinkCurrentPart());
template <bool is_ascii, typename Char>
INLINE(void Append_(Char c));
@@ -84,6 +87,11 @@ class BasicJsonStringifier BASE_EMBEDDED {
bool deferred_comma,
bool deferred_key);
+ template <typename ResultType, typename Char>
+ INLINE(static MaybeObject* StringifyString_(Isolate* isolate,
+ Vector<Char> vector,
+ Handle<String> result));
+
// Entry point to serialize the object.
INLINE(Result SerializeObject(Handle<Object> obj)) {
return Serialize_<false>(obj, false, factory_->empty_string());
@@ -135,18 +143,18 @@ class BasicJsonStringifier BASE_EMBEDDED {
void SerializeString(Handle<String> object);
template <typename SrcChar, typename DestChar>
- INLINE(void SerializeStringUnchecked_(const SrcChar* src,
- DestChar* dest,
- int length));
+ INLINE(static int SerializeStringUnchecked_(const SrcChar* src,
+ DestChar* dest,
+ int length));
template <bool is_ascii, typename Char>
INLINE(void SerializeString_(Handle<String> string));
template <typename Char>
- INLINE(bool DoNotEscape(Char c));
+ INLINE(static bool DoNotEscape(Char c));
template <typename Char>
- INLINE(Vector<const Char> GetCharVector(Handle<String> string));
+ INLINE(static Vector<const Char> GetCharVector(Handle<String> string));
Result StackPush(Handle<Object> object);
void StackPop();
@@ -244,15 +252,15 @@ const char* const BasicJsonStringifier::JsonEscapeTable =
"\370\0 \371\0 \372\0 \373\0 "
"\374\0 \375\0 \376\0 \377\0 ";
+
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
: isolate_(isolate), current_index_(0), is_ascii_(true) {
factory_ = isolate_->factory();
accumulator_store_ = Handle<JSValue>::cast(
factory_->ToObject(factory_->empty_string()));
part_length_ = kInitialPartLength;
- current_part_ = factory_->NewRawOneByteString(kInitialPartLength);
- tojson_string_ =
- factory_->InternalizeOneByteString(STATIC_ASCII_VECTOR("toJSON"));
+ current_part_ = factory_->NewRawOneByteString(part_length_);
+ tojson_string_ = factory_->toJSON_string();
stack_ = factory_->NewJSArray(8);
}
@@ -275,6 +283,51 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
}
+MaybeObject* BasicJsonStringifier::StringifyString(Isolate* isolate,
+ Handle<String> object) {
+ static const int kJsonQuoteWorstCaseBlowup = 6;
+ static const int kSpaceForQuotes = 2;
+ int worst_case_length =
+ object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
+
+ if (worst_case_length > 32 * KB) { // Slow path if too large.
+ BasicJsonStringifier stringifier(isolate);
+ return stringifier.Stringify(object);
+ }
+
+ FlattenString(object);
+ String::FlatContent flat = object->GetFlatContent();
+ if (flat.IsAscii()) {
+ return StringifyString_<SeqOneByteString>(
+ isolate,
+ flat.ToOneByteVector(),
+ isolate->factory()->NewRawOneByteString(worst_case_length));
+ } else {
+ ASSERT(flat.IsTwoByte());
+ return StringifyString_<SeqTwoByteString>(
+ isolate,
+ flat.ToUC16Vector(),
+ isolate->factory()->NewRawTwoByteString(worst_case_length));
+ }
+}
+
+
+template <typename ResultType, typename Char>
+MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate,
+ Vector<Char> vector,
+ Handle<String> result) {
+ AssertNoAllocation no_allocation;
+ int final_size = 0;
+ ResultType* dest = ResultType::cast(*result);
+ dest->Set(final_size++, '\"');
+ final_size += SerializeStringUnchecked_(vector.start(),
+ dest->GetChars() + 1,
+ vector.length());
+ dest->Set(final_size++, '\"');
+ return *SeqString::Truncate(Handle<SeqString>::cast(result), final_size);
+}
+
+
template <bool is_ascii, typename Char>
void BasicJsonStringifier::Append_(Char c) {
if (is_ascii) {
@@ -638,8 +691,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
void BasicJsonStringifier::ShrinkCurrentPart() {
ASSERT(current_index_ < part_length_);
- current_part_ = Handle<String>(
- SeqString::cast(*current_part_)->Truncate(current_index_), isolate_);
+ current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_),
+ current_index_);
}
@@ -667,10 +720,9 @@ void BasicJsonStringifier::ChangeEncoding() {
template <typename SrcChar, typename DestChar>
-void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
- DestChar* dest,
- int length) {
- dest += current_index_;
+int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
+ DestChar* dest,
+ int length) {
DestChar* dest_start = dest;
// Assert that uc16 character is not truncated down to 8 bit.
@@ -688,7 +740,7 @@ void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
}
}
- current_index_ += static_cast<int>(dest - dest_start);
+ return static_cast<int>(dest - dest_start);
}
@@ -705,14 +757,14 @@ void BasicJsonStringifier::SerializeString_(Handle<String> string) {
AssertNoAllocation no_allocation;
Vector<const Char> vector = GetCharVector<Char>(string);
if (is_ascii) {
- SerializeStringUnchecked_(
+ current_index_ += SerializeStringUnchecked_(
vector.start(),
- SeqOneByteString::cast(*current_part_)->GetChars(),
+ SeqOneByteString::cast(*current_part_)->GetChars() + current_index_,
length);
} else {
- SerializeStringUnchecked_(
+ current_index_ += SerializeStringUnchecked_(
vector.start(),
- SeqTwoByteString::cast(*current_part_)->GetChars(),
+ SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_,
length);
}
} else {
diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc
index e9ef38215..94385373c 100644
--- a/deps/v8/src/log.cc
+++ b/deps/v8/src/log.cc
@@ -644,7 +644,17 @@ void Logger::ApiNamedSecurityCheck(Object* key) {
String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ApiEvent("api,check-security,\"%s\"\n", *str);
} else if (key->IsSymbol()) {
- ApiEvent("api,check-security,symbol(hash %x)\n", Symbol::cast(key)->Hash());
+ Symbol* symbol = Symbol::cast(key);
+ if (symbol->name()->IsUndefined()) {
+ ApiEvent("api,check-security,symbol(hash %x)\n",
+ Symbol::cast(key)->Hash());
+ } else {
+ SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
+ DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ ApiEvent("api,check-security,symbol(\"%s\" hash %x)\n",
+ *str,
+ Symbol::cast(key)->Hash());
+ }
} else if (key->IsUndefined()) {
ApiEvent("api,check-security,undefined\n");
} else {
@@ -833,8 +843,16 @@ void Logger::ApiNamedPropertyAccess(const char* tag,
String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
} else {
- uint32_t hash = Symbol::cast(name)->Hash();
- ApiEvent("api,%s,\"%s\",symbol(hash %x)\n", tag, *class_name, hash);
+ Symbol* symbol = Symbol::cast(name);
+ uint32_t hash = symbol->Hash();
+ if (symbol->name()->IsUndefined()) {
+ ApiEvent("api,%s,\"%s\",symbol(hash %x)\n", tag, *class_name, hash);
+ } else {
+ SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
+ DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)\n",
+ tag, *class_name, *str, hash);
+ }
}
}
@@ -902,7 +920,14 @@ void Logger::CallbackEventInternal(const char* prefix, Name* name,
String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append(",1,\"%s%s\"", prefix, *str);
} else {
- msg.Append(",1,symbol(hash %x)", prefix, Name::cast(name)->Hash());
+ Symbol* symbol = Symbol::cast(name);
+ if (symbol->name()->IsUndefined()) {
+ msg.Append(",1,symbol(hash %x)", prefix, symbol->Hash());
+ } else {
+ SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
+ DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+ msg.Append(",1,symbol(\"%s\" hash %x)", prefix, *str, symbol->Hash());
+ }
}
msg.Append('\n');
msg.WriteToLogFile();
@@ -978,8 +1003,15 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
if (name->IsString()) {
name_buffer_->AppendString(String::cast(name));
} else {
- name_buffer_->AppendBytes("symbol(hash ");
- name_buffer_->AppendHex(Name::cast(name)->Hash());
+ Symbol* symbol = Symbol::cast(name);
+ name_buffer_->AppendBytes("symbol(");
+ if (!symbol->name()->IsUndefined()) {
+ name_buffer_->AppendBytes("\"");
+ name_buffer_->AppendString(String::cast(symbol->name()));
+ name_buffer_->AppendBytes("\" ");
+ }
+ name_buffer_->AppendBytes("hash ");
+ name_buffer_->AppendHex(symbol->Hash());
name_buffer_->AppendByte(')');
}
}
@@ -1006,7 +1038,14 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
msg.AppendDetailed(String::cast(name), false);
msg.Append('"');
} else {
- msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+ Symbol* symbol = Symbol::cast(name);
+ msg.Append("symbol(");
+ if (!symbol->name()->IsUndefined()) {
+ msg.Append("\"");
+ msg.AppendDetailed(String::cast(symbol->name()), false);
+ msg.Append("\" ");
+ }
+ msg.Append("hash %x)", symbol->Hash());
}
msg.Append('\n');
msg.WriteToLogFile();
@@ -1036,8 +1075,15 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
if (name->IsString()) {
name_buffer_->AppendString(String::cast(name));
} else {
- name_buffer_->AppendBytes("symbol(hash ");
- name_buffer_->AppendHex(Name::cast(name)->Hash());
+ Symbol* symbol = Symbol::cast(name);
+ name_buffer_->AppendBytes("symbol(");
+ if (!symbol->name()->IsUndefined()) {
+ name_buffer_->AppendBytes("\"");
+ name_buffer_->AppendString(String::cast(symbol->name()));
+ name_buffer_->AppendBytes("\" ");
+ }
+ name_buffer_->AppendBytes("hash ");
+ name_buffer_->AppendHex(symbol->Hash());
name_buffer_->AppendByte(')');
}
}
@@ -1073,7 +1119,14 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("\"%s\"", *str);
} else {
- msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+ Symbol* symbol = Symbol::cast(name);
+ msg.Append("symbol(");
+ if (!symbol->name()->IsUndefined()) {
+ msg.Append("\"");
+ msg.AppendDetailed(String::cast(symbol->name()), false);
+ msg.Append("\" ");
+ }
+ msg.Append("hash %x)", symbol->Hash());
}
msg.Append(',');
msg.AppendAddress(shared->address());
@@ -1138,7 +1191,14 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
String::cast(source)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s", *sourcestr);
} else {
- msg.Append("symbol(hash %x)", Name::cast(source)->Hash());
+ Symbol* symbol = Symbol::cast(source);
+ msg.Append("symbol(");
+ if (!symbol->name()->IsUndefined()) {
+ msg.Append("\"");
+ msg.AppendDetailed(String::cast(symbol->name()), false);
+ msg.Append("\" ");
+ }
+ msg.Append("hash %x)", symbol->Hash());
}
msg.Append(":%d\",", line);
msg.AppendAddress(shared->address());
@@ -1358,7 +1418,14 @@ void Logger::SuspectReadEvent(Name* name, Object* obj) {
msg.Append(String::cast(name));
msg.Append('"');
} else {
- msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+ Symbol* symbol = Symbol::cast(name);
+ msg.Append("symbol(");
+ if (!symbol->name()->IsUndefined()) {
+ msg.Append("\"");
+ msg.AppendDetailed(String::cast(symbol->name()), false);
+ msg.Append("\" ");
+ }
+ msg.Append("hash %x)", symbol->Hash());
}
msg.Append('\n');
msg.WriteToLogFile();
diff --git a/deps/v8/src/log.h b/deps/v8/src/log.h
index 5c121bc31..a5eddc7a3 100644
--- a/deps/v8/src/log.h
+++ b/deps/v8/src/log.h
@@ -77,6 +77,7 @@ class Semaphore;
class Ticker;
class Isolate;
class PositionsRecorder;
+class CpuProfiler;
#undef LOG
#define LOG(isolate, Call) \
diff --git a/deps/v8/src/macros.py b/deps/v8/src/macros.py
index 291a898f5..92ed437b0 100644
--- a/deps/v8/src/macros.py
+++ b/deps/v8/src/macros.py
@@ -99,7 +99,7 @@ macro IS_UNDEFINED(arg) = (typeof(arg) === 'undefined');
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
-macro IS_SYMBOL(arg) = (%_IsSymbol(arg));
+macro IS_SYMBOL(arg) = (typeof(arg) === 'symbol');
macro IS_OBJECT(arg) = (%_IsObject(arg));
macro IS_ARRAY(arg) = (%_IsArray(arg));
macro IS_FUNCTION(arg) = (%_IsFunction(arg));
@@ -110,11 +110,13 @@ macro IS_WEAKMAP(arg) = (%_ClassOf(arg) === 'WeakMap');
macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String');
+macro IS_SYMBOL_WRAPPER(arg) = (%_ClassOf(arg) === 'Symbol');
macro IS_BOOLEAN_WRAPPER(arg) = (%_ClassOf(arg) === 'Boolean');
macro IS_ERROR(arg) = (%_ClassOf(arg) === 'Error');
macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script');
macro IS_ARGUMENTS(arg) = (%_ClassOf(arg) === 'Arguments');
macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global');
+macro IS_ARRAYBUFFER(arg) = (%_ClassOf(arg) === '__ArrayBuffer');
macro IS_UNDETECTABLE(arg) = (%_IsUndetectableObject(arg));
macro FLOOR(arg) = $floor(arg);
@@ -141,6 +143,7 @@ const kBoundArgumentsStartIndex = 2;
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || ((arg == arg) && (arg != 1/0) && (arg != -1/0)));
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
+macro TO_POSITIVE_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? (arg > 0 ? arg : 0) : %NumberToPositiveInteger(ToNumber(arg)));
macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
macro TO_UINT32(arg) = (arg >>> 0);
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index 7353444b4..d51d38475 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -100,6 +100,7 @@ var kMessages = {
observe_notify_non_notifier: ["notify called on non-notifier object"],
// RangeError
invalid_array_length: ["Invalid array length"],
+ invalid_array_buffer_length: ["Invalid array buffer length"],
stack_overflow: ["Maximum call stack size exceeded"],
invalid_time_value: ["Invalid time value"],
// SyntaxError
@@ -150,6 +151,7 @@ var kMessages = {
cant_prevent_ext_external_array_elements: ["Cannot prevent extension of an object with external array elements"],
redef_external_array_element: ["Cannot redefine a property of an object with external array elements"],
harmony_const_assign: ["Assignment to constant variable."],
+ symbol_to_string: ["Conversion from symbol to string"],
invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"],
module_type_error: ["Module '", "%0", "' used improperly"],
module_export_undefined: ["Export '", "%0", "' is not defined in module"],
@@ -745,64 +747,70 @@ function GetPositionInLine(message) {
function GetStackTraceLine(recv, fun, pos, isGlobal) {
- return new CallSite(recv, fun, pos).toString();
+ return new CallSite(recv, fun, pos, false).toString();
}
// ----------------------------------------------------------------------------
// Error implementation
-function CallSite(receiver, fun, pos) {
- this.receiver = receiver;
- this.fun = fun;
- this.pos = pos;
+var CallSiteReceiverKey = %CreateSymbol("receiver");
+var CallSiteFunctionKey = %CreateSymbol("function");
+var CallSitePositionKey = %CreateSymbol("position");
+var CallSiteStrictModeKey = %CreateSymbol("strict mode");
+
+function CallSite(receiver, fun, pos, strict_mode) {
+ this[CallSiteReceiverKey] = receiver;
+ this[CallSiteFunctionKey] = fun;
+ this[CallSitePositionKey] = pos;
+ this[CallSiteStrictModeKey] = strict_mode;
}
function CallSiteGetThis() {
- return this.receiver;
+ return this[CallSiteStrictModeKey] ? void 0 : this[CallSiteReceiverKey];
}
function CallSiteGetTypeName() {
- return GetTypeName(this, false);
+ return GetTypeName(this[CallSiteReceiverKey], false);
}
function CallSiteIsToplevel() {
- if (this.receiver == null) {
+ if (this[CallSiteReceiverKey] == null) {
return true;
}
- return IS_GLOBAL(this.receiver);
+ return IS_GLOBAL(this[CallSiteReceiverKey]);
}
function CallSiteIsEval() {
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
return script && script.compilation_type == COMPILATION_TYPE_EVAL;
}
function CallSiteGetEvalOrigin() {
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
return FormatEvalOrigin(script);
}
function CallSiteGetScriptNameOrSourceURL() {
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
return script ? script.nameOrSourceURL() : null;
}
function CallSiteGetFunction() {
- return this.fun;
+ return this[CallSiteStrictModeKey] ? void 0 : this[CallSiteFunctionKey];
}
function CallSiteGetFunctionName() {
// See if the function knows its own name
- var name = this.fun.name;
+ var name = this[CallSiteFunctionKey].name;
if (name) {
return name;
}
- name = %FunctionGetInferredName(this.fun);
+ name = %FunctionGetInferredName(this[CallSiteFunctionKey]);
if (name) {
return name;
}
// Maybe this is an evaluation?
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
return "eval";
}
@@ -812,26 +820,22 @@ function CallSiteGetFunctionName() {
function CallSiteGetMethodName() {
// See if we can find a unique property on the receiver that holds
// this function.
- var ownName = this.fun.name;
- if (ownName && this.receiver &&
- (%_CallFunction(this.receiver,
- ownName,
- ObjectLookupGetter) === this.fun ||
- %_CallFunction(this.receiver,
- ownName,
- ObjectLookupSetter) === this.fun ||
- (IS_OBJECT(this.receiver) &&
- %GetDataProperty(this.receiver, ownName) === this.fun))) {
+ var receiver = this[CallSiteReceiverKey];
+ var fun = this[CallSiteFunctionKey];
+ var ownName = fun.name;
+ if (ownName && receiver &&
+ (%_CallFunction(receiver, ownName, ObjectLookupGetter) === fun ||
+ %_CallFunction(receiver, ownName, ObjectLookupSetter) === fun ||
+ (IS_OBJECT(receiver) && %GetDataProperty(receiver, ownName) === fun))) {
// To handle DontEnum properties we guess that the method has
// the same name as the function.
return ownName;
}
var name = null;
- for (var prop in this.receiver) {
- if (%_CallFunction(this.receiver, prop, ObjectLookupGetter) === this.fun ||
- %_CallFunction(this.receiver, prop, ObjectLookupSetter) === this.fun ||
- (IS_OBJECT(this.receiver) &&
- %GetDataProperty(this.receiver, prop) === this.fun)) {
+ for (var prop in receiver) {
+ if (%_CallFunction(receiver, prop, ObjectLookupGetter) === fun ||
+ %_CallFunction(receiver, prop, ObjectLookupSetter) === fun ||
+ (IS_OBJECT(receiver) && %GetDataProperty(receiver, prop) === fun)) {
// If we find more than one match bail out to avoid confusion.
if (name) {
return null;
@@ -846,49 +850,49 @@ function CallSiteGetMethodName() {
}
function CallSiteGetFileName() {
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
return script ? script.name : null;
}
function CallSiteGetLineNumber() {
- if (this.pos == -1) {
+ if (this[CallSitePositionKey] == -1) {
return null;
}
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
var location = null;
if (script) {
- location = script.locationFromPosition(this.pos, true);
+ location = script.locationFromPosition(this[CallSitePositionKey], true);
}
return location ? location.line + 1 : null;
}
function CallSiteGetColumnNumber() {
- if (this.pos == -1) {
+ if (this[CallSitePositionKey] == -1) {
return null;
}
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
var location = null;
if (script) {
- location = script.locationFromPosition(this.pos, true);
+ location = script.locationFromPosition(this[CallSitePositionKey], true);
}
return location ? location.column + 1: null;
}
function CallSiteIsNative() {
- var script = %FunctionGetScript(this.fun);
+ var script = %FunctionGetScript(this[CallSiteFunctionKey]);
return script ? (script.type == TYPE_NATIVE) : false;
}
function CallSiteGetPosition() {
- return this.pos;
+ return this[CallSitePositionKey];
}
function CallSiteIsConstructor() {
- var receiver = this.receiver;
+ var receiver = this[CallSiteReceiverKey];
var constructor =
IS_OBJECT(receiver) ? %GetDataProperty(receiver, "constructor") : null;
if (!constructor) return false;
- return this.fun === constructor;
+ return this[CallSiteFunctionKey] === constructor;
}
function CallSiteToString() {
@@ -931,7 +935,7 @@ function CallSiteToString() {
var isConstructor = this.isConstructor();
var isMethodCall = !(this.isToplevel() || isConstructor);
if (isMethodCall) {
- var typeName = GetTypeName(this, true);
+ var typeName = GetTypeName(this[CallSiteReceiverKey], true);
var methodName = this.getMethodName();
if (functionName) {
if (typeName &&
@@ -1035,13 +1039,15 @@ function FormatErrorString(error) {
function GetStackFrames(raw_stack) {
var frames = new InternalArray();
- for (var i = 0; i < raw_stack.length; i += 4) {
+ var non_strict_frames = raw_stack[0];
+ for (var i = 1; i < raw_stack.length; i += 4) {
var recv = raw_stack[i];
var fun = raw_stack[i + 1];
var code = raw_stack[i + 2];
var pc = raw_stack[i + 3];
var pos = %FunctionGetPositionForOffset(code, pc);
- frames.push(new CallSite(recv, fun, pos));
+ non_strict_frames--;
+ frames.push(new CallSite(recv, fun, pos, (non_strict_frames < 0)));
}
return frames;
}
@@ -1069,16 +1075,16 @@ function FormatStackTrace(error_string, frames) {
}
-function GetTypeName(obj, requireConstructor) {
- var constructor = obj.receiver.constructor;
+function GetTypeName(receiver, requireConstructor) {
+ var constructor = receiver.constructor;
if (!constructor) {
return requireConstructor ? null :
- %_CallFunction(obj.receiver, ObjectToString);
+ %_CallFunction(receiver, ObjectToString);
}
var constructorName = constructor.name;
if (!constructorName) {
return requireConstructor ? null :
- %_CallFunction(obj.receiver, ObjectToString);
+ %_CallFunction(receiver, ObjectToString);
}
return constructorName;
}
diff --git a/deps/v8/src/mips/OWNERS b/deps/v8/src/mips/OWNERS
new file mode 100644
index 000000000..3cb222c46
--- /dev/null
+++ b/deps/v8/src/mips/OWNERS
@@ -0,0 +1 @@
+plind44@gmail.com
diff --git a/deps/v8/src/mips/assembler-mips.cc b/deps/v8/src/mips/assembler-mips.cc
index 4c11c7f54..c255d0fbd 100644
--- a/deps/v8/src/mips/assembler-mips.cc
+++ b/deps/v8/src/mips/assembler-mips.cc
@@ -490,7 +490,6 @@ bool Assembler::IsBranch(Instr instr) {
uint32_t opcode = GetOpcodeField(instr);
uint32_t rt_field = GetRtField(instr);
uint32_t rs_field = GetRsField(instr);
- uint32_t label_constant = GetLabelConst(instr);
// Checks if the instruction is a branch.
return opcode == BEQ ||
opcode == BNE ||
@@ -502,10 +501,13 @@ bool Assembler::IsBranch(Instr instr) {
opcode == BGTZL ||
(opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
rt_field == BLTZAL || rt_field == BGEZAL)) ||
- (opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
- label_constant == 0; // Emitted label const in reg-exp engine.
+ (opcode == COP1 && rs_field == BC1); // Coprocessor branch.
}
+bool Assembler::IsEmittedConstant(Instr instr) {
+ uint32_t label_constant = GetLabelConst(instr);
+ return label_constant == 0; // Emitted label const in reg-exp engine.
+}
bool Assembler::IsBeq(Instr instr) {
return GetOpcodeField(instr) == BEQ;
@@ -796,7 +798,7 @@ void Assembler::bind_to(Label* L, int pos) {
}
target_at_put(fixup_pos, pos);
} else {
- ASSERT(IsJ(instr) || IsLui(instr));
+ ASSERT(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr));
target_at_put(fixup_pos, pos);
}
}
diff --git a/deps/v8/src/mips/assembler-mips.h b/deps/v8/src/mips/assembler-mips.h
index e6c9e76c7..9d3d39b83 100644
--- a/deps/v8/src/mips/assembler-mips.h
+++ b/deps/v8/src/mips/assembler-mips.h
@@ -942,6 +942,7 @@ class Assembler : public AssemblerBase {
static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
static bool IsAndImmediate(Instr instr);
+ static bool IsEmittedConstant(Instr instr);
void CheckTrampolinePool();
diff --git a/deps/v8/src/mips/builtins-mips.cc b/deps/v8/src/mips/builtins-mips.cc
index 54efd9491..1901f9c41 100644
--- a/deps/v8/src/mips/builtins-mips.cc
+++ b/deps/v8/src/mips/builtins-mips.cc
@@ -227,13 +227,12 @@ static void AllocateJSArray(MacroAssembler* masm,
(JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
__ sra(scratch1, array_size, kSmiTagSize);
__ Addu(elements_array_end, elements_array_end, scratch1);
- __ AllocateInNewSpace(
- elements_array_end,
- result,
- scratch1,
- scratch2,
- gc_required,
- static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
+ __ Allocate(elements_array_end,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
@@ -895,7 +894,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// a1: constructor function
// a2: initial map
__ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
- __ AllocateInNewSpace(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
+ __ Allocate(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
// Allocated the JSObject, now initialize the fields. Map is set to
// initial map and properties and elements are set to empty fixed array.
@@ -974,7 +973,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// t4: JSObject
// t5: start of next object
__ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
- __ AllocateInNewSpace(
+ __ Allocate(
a0,
t5,
t6,
@@ -1130,10 +1129,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ GetObjectType(v0, a1, a3);
__ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
- // Symbols are "objects".
- __ lbu(a3, FieldMemOperand(a1, Map::kInstanceTypeOffset));
- __ Branch(&exit, eq, a3, Operand(SYMBOL_TYPE));
-
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ bind(&use_receiver);
diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc
index f5908d37b..37d7720c8 100644
--- a/deps/v8/src/mips/code-stubs-mips.cc
+++ b/deps/v8/src/mips/code-stubs-mips.cc
@@ -62,6 +62,17 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
}
+void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { a2, a1, a0 };
+ descriptor->register_param_count_ = 3;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure);
+}
+
+
void TransitionElementsKindStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -85,7 +96,7 @@ static void InitializeArrayConstructorDescriptor(Isolate* isolate,
// stack param count needs (constructor pointer, and single argument)
descriptor->stack_parameter_count_ = &a0;
descriptor->register_params_ = registers;
- descriptor->extra_expression_stack_count_ = 1;
+ descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
descriptor->deoptimization_handler_ =
FUNCTION_ADDR(ArrayConstructor_StubFailure);
}
@@ -673,6 +684,8 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
Register scratch1,
Register scratch2,
Label* not_number) {
+ ASSERT(!object.is(dst1) && !object.is(dst2));
+
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
"HeapNumberMap register clobbered.");
@@ -867,6 +880,10 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
ASSERT(!heap_number_map.is(object) &&
!heap_number_map.is(scratch1) &&
!heap_number_map.is(scratch2));
+ // ARM uses pop/push and Ldlr to save dst_* and probably object registers in
+ // softfloat path. On MIPS there is no ldlr, 1st lw instruction may overwrite
+ // object register making the 2nd lw invalid.
+ ASSERT(!object.is(dst_mantissa) && !object.is(dst_exponent));
Label done, obj_is_not_smi;
@@ -903,49 +920,24 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
if (destination == kCoreRegisters) {
__ Move(dst_mantissa, dst_exponent, double_dst);
}
-
} else {
- ASSERT(!scratch1.is(object) && !scratch2.is(object));
// Load the double value in the destination registers.
- bool save_registers = object.is(dst_mantissa) || object.is(dst_exponent);
- if (save_registers) {
- // Save both output registers, because the other one probably holds
- // an important value too.
- __ Push(dst_exponent, dst_mantissa);
- }
__ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
__ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset));
// Check for 0 and -0.
- Label zero;
__ And(scratch1, dst_exponent, Operand(~HeapNumber::kSignMask));
__ Or(scratch1, scratch1, Operand(dst_mantissa));
- __ Branch(&zero, eq, scratch1, Operand(zero_reg));
+ __ Branch(&done, eq, scratch1, Operand(zero_reg));
// Check that the value can be exactly represented by a 32-bit integer.
// Jump to not_int32 if that's not the case.
- Label restore_input_and_miss;
DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2,
- &restore_input_and_miss);
+ not_int32);
// dst_* were trashed. Reload the double value.
- if (save_registers) {
- __ Pop(dst_exponent, dst_mantissa);
- }
__ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
__ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset));
- __ Branch(&done);
-
- __ bind(&restore_input_and_miss);
- if (save_registers) {
- __ Pop(dst_exponent, dst_mantissa);
- }
- __ Branch(not_int32);
-
- __ bind(&zero);
- if (save_registers) {
- __ Drop(2);
- }
}
__ bind(&done);
@@ -2696,16 +2688,20 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
masm, destination, right, f14, a2, a3, heap_number_map,
scratch1, scratch2, fail);
}
+ // Use scratch3 as left in LoadNumber functions to avoid overwriting of
+ // left (a0) register.
+ __ mov(scratch3, left);
+
// Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it
// jumps to |miss|.
if (left_type == BinaryOpIC::INT32) {
FloatingPointHelper::LoadNumberAsInt32Double(
- masm, left, destination, f12, f16, a0, a1, heap_number_map,
+ masm, scratch3, destination, f12, f16, a0, a1, heap_number_map,
scratch1, scratch2, f2, miss);
} else {
Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
FloatingPointHelper::LoadNumber(
- masm, destination, left, f12, a0, a1, heap_number_map,
+ masm, destination, scratch3, f12, a0, a1, heap_number_map,
scratch1, scratch2, fail);
}
}
@@ -4544,35 +4540,6 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
}
-void ArrayLengthStub::Generate(MacroAssembler* masm) {
- Label miss;
- Register receiver;
- if (kind() == Code::KEYED_LOAD_IC) {
- // ----------- S t a t e -------------
- // -- ra : return address
- // -- a0 : key
- // -- a1 : receiver
- // -----------------------------------
- __ Branch(&miss, ne, a0,
- Operand(masm->isolate()->factory()->length_string()));
- receiver = a1;
- } else {
- ASSERT(kind() == Code::LOAD_IC);
- // ----------- S t a t e -------------
- // -- a2 : name
- // -- ra : return address
- // -- a0 : receiver
- // -- sp[0] : receiver
- // -----------------------------------
- receiver = a0;
- }
-
- StubCompiler::GenerateLoadArrayLength(masm, receiver, a3, &miss);
- __ bind(&miss);
- StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
-}
-
-
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver;
@@ -4861,7 +4828,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
__ Addu(t5, t5, Operand(Heap::kArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ AllocateInNewSpace(t5, v0, a3, t0, &runtime, TAG_OBJECT);
+ __ Allocate(t5, v0, a3, t0, &runtime, TAG_OBJECT);
// v0 = address of new object(s) (tagged)
// a2 = argument count (tagged)
@@ -5052,13 +5019,8 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
__ Addu(a1, a1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
// Do the allocation of both objects in one go.
- __ AllocateInNewSpace(a1,
- v0,
- a2,
- a3,
- &runtime,
- static_cast<AllocationFlags>(TAG_OBJECT |
- SIZE_IN_WORDS));
+ __ Allocate(a1, v0, a2, a3, &runtime,
+ static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Get the arguments boilerplate from the current native context.
__ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
@@ -5578,7 +5540,7 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
(JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
__ srl(t1, a1, kSmiTagSize + kSmiShiftSize);
__ Addu(a2, t1, Operand(objects_size));
- __ AllocateInNewSpace(
+ __ Allocate(
a2, // In: Size, in words.
v0, // Out: Start of allocation (tagged).
a3, // Scratch register.
@@ -7543,30 +7505,28 @@ void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
__ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
__ Branch(done, eq, entity_name, Operand(tmp));
- if (i != kInlinedProbes - 1) {
- // Load the hole ready for use below:
- __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
+ // Load the hole ready for use below:
+ __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
+
+ // Stop if found the property.
+ __ Branch(miss, eq, entity_name, Operand(Handle<Name>(name)));
- // Stop if found the property.
- __ Branch(miss, eq, entity_name, Operand(Handle<Name>(name)));
+ Label good;
+ __ Branch(&good, eq, entity_name, Operand(tmp));
- Label good;
- __ Branch(&good, eq, entity_name, Operand(tmp));
+ // Check if the entry name is not a unique name.
+ __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
+ __ lbu(entity_name,
+ FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+ __ And(scratch0, entity_name, Operand(kIsInternalizedMask));
+ __ Branch(&good, ne, scratch0, Operand(zero_reg));
+ __ Branch(miss, ne, entity_name, Operand(SYMBOL_TYPE));
- // Check if the entry name is not a unique name.
- __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
- __ lbu(entity_name,
- FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
- __ And(scratch0, entity_name, Operand(kIsInternalizedMask));
- __ Branch(&good, ne, scratch0, Operand(zero_reg));
- __ Branch(miss, ne, entity_name, Operand(SYMBOL_TYPE));
-
- __ bind(&good);
-
- // Restore the properties.
- __ lw(properties,
- FieldMemOperand(receiver, JSObject::kPropertiesOffset));
- }
+ __ bind(&good);
+
+ // Restore the properties.
+ __ lw(properties,
+ FieldMemOperand(receiver, JSObject::kPropertiesOffset));
}
const int spill_mask =
@@ -8127,6 +8087,9 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
int parameter_count_offset =
StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
__ lw(a1, MemOperand(fp, parameter_count_offset));
+ if (function_mode_ == JS_FUNCTION_STUB_MODE) {
+ __ Addu(a1, a1, Operand(1));
+ }
masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
__ sll(a1, a1, kPointerSizeLog2);
__ Addu(sp, sp, a1);
diff --git a/deps/v8/src/mips/codegen-mips.cc b/deps/v8/src/mips/codegen-mips.cc
index f5cb5e489..bd403cee6 100644
--- a/deps/v8/src/mips/codegen-mips.cc
+++ b/deps/v8/src/mips/codegen-mips.cc
@@ -206,8 +206,9 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
// Allocate new FixedDoubleArray.
__ sll(scratch, t1, 2);
__ Addu(scratch, scratch, FixedDoubleArray::kHeaderSize);
- __ AllocateInNewSpace(scratch, t2, t3, t5, &gc_required, NO_ALLOCATION_FLAGS);
+ __ Allocate(scratch, t2, t3, t5, &gc_required, NO_ALLOCATION_FLAGS);
// t2: destination FixedDoubleArray, not tagged as heap object
+
// Set destination FixedDoubleArray's length and map.
__ LoadRoot(t5, Heap::kFixedDoubleArrayMapRootIndex);
__ sw(t1, MemOperand(t2, FixedDoubleArray::kLengthOffset));
@@ -351,7 +352,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
// Allocate new FixedArray.
__ sll(a0, t1, 1);
__ Addu(a0, a0, FixedDoubleArray::kHeaderSize);
- __ AllocateInNewSpace(a0, t2, t3, t5, &gc_required, NO_ALLOCATION_FLAGS);
+ __ Allocate(a0, t2, t3, t5, &gc_required, NO_ALLOCATION_FLAGS);
// t2: destination FixedArray, not tagged as heap object
// Set destination FixedDoubleArray's length and map.
__ LoadRoot(t5, Heap::kFixedArrayMapRootIndex);
@@ -702,7 +703,7 @@ void Code::PatchPlatformCodeAge(byte* sequence,
uint32_t young_length;
byte* young_sequence = GetNoCodeAgeSequence(&young_length);
if (age == kNoAge) {
- memcpy(sequence, young_sequence, young_length);
+ CopyBytes(sequence, young_sequence, young_length);
CPU::FlushICache(sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(age, parity);
diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc
index bacec10f0..3e7c8da7a 100644
--- a/deps/v8/src/mips/full-codegen-mips.cc
+++ b/deps/v8/src/mips/full-codegen-mips.cc
@@ -2780,28 +2780,6 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
}
-void FullCodeGenerator::EmitIsSymbol(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(v0, if_false);
- __ GetObjectType(v0, a1, a2);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, a2, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1);
@@ -4320,6 +4298,10 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ And(a1, a1, Operand(1 << Map::kIsUndetectable));
Split(eq, a1, Operand(zero_reg),
if_true, if_false, fall_through);
+ } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ __ JumpIfSmi(v0, if_false);
+ __ GetObjectType(v0, v0, a1);
+ Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(if_true, eq, v0, Operand(at));
@@ -4351,10 +4333,6 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ LoadRoot(at, Heap::kNullValueRootIndex);
__ Branch(if_true, eq, v0, Operand(at));
}
- if (FLAG_harmony_symbols) {
- __ GetObjectType(v0, v0, a1);
- __ Branch(if_true, eq, a1, Operand(SYMBOL_TYPE));
- }
// Check for JS objects => true.
__ GetObjectType(v0, v0, a1);
__ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc
index cd489346a..b5d6c451f 100644
--- a/deps/v8/src/mips/lithium-codegen-mips.cc
+++ b/deps/v8/src/mips/lithium-codegen-mips.cc
@@ -237,7 +237,7 @@ bool LCodeGen::GeneratePrologue() {
__ sw(a0, target);
// Update the write barrier. This clobbers a3 and a0.
__ RecordWriteContextSlot(
- cp, target.offset(), a0, a3, kRAHasBeenSaved, kSaveFPRegs);
+ cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs);
}
}
Comment(";;; End allocate local context");
@@ -1492,13 +1492,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
-void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
- Register result = ToRegister(instr->result());
- Register array = ToRegister(instr->value());
- __ lw(result, FieldMemOperand(array, JSArray::kLengthOffset));
-}
-
-
void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
@@ -1901,6 +1894,13 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ bind(&not_string);
}
+ if (expected.Contains(ToBooleanStub::SYMBOL)) {
+ // Symbol value -> true.
+ const Register scratch = scratch1();
+ __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+ __ Branch(true_label, eq, scratch, Operand(SYMBOL_TYPE));
+ }
+
if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
CpuFeatureScope scope(masm(), FPU);
// heap number -> false iff +0, -0, or NaN.
@@ -2687,7 +2687,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
target.offset(),
value,
scratch0(),
- kRAHasBeenSaved,
+ GetRAState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4030,7 +4030,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
HeapObject::kMapOffset,
scratch,
temp,
- kRAHasBeenSaved,
+ GetRAState(),
kSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
@@ -4049,7 +4049,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
offset,
value,
scratch,
- kRAHasBeenSaved,
+ GetRAState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4064,7 +4064,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
offset,
value,
object,
- kRAHasBeenSaved,
+ GetRAState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4275,7 +4275,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
__ RecordWrite(elements,
key,
value,
- kRAHasBeenSaved,
+ GetRAState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
@@ -4326,7 +4326,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
__ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
// Write barrier.
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
- scratch, kRAHasBeenSaved, kDontSaveFPRegs);
+ scratch, GetRAState(), kDontSaveFPRegs);
} else if (FLAG_compiled_transitions) {
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
__ mov(a0, object_reg);
@@ -4571,10 +4571,11 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
// Convert unsigned integer with specified number of leading zeroes in binary
// representation to IEEE 754 double.
-// Integer to convert is passed in register hiword.
+// Integer to convert is passed in register src.
// Resulting double is returned in registers hiword:loword.
// This functions does not work correctly for 0.
static void GenerateUInt2Double(MacroAssembler* masm,
+ Register src,
Register hiword,
Register loword,
Register scratch,
@@ -4588,12 +4589,12 @@ static void GenerateUInt2Double(MacroAssembler* masm,
kBitsPerInt - mantissa_shift_for_hi_word;
masm->li(scratch, Operand(biased_exponent << HeapNumber::kExponentShift));
if (mantissa_shift_for_hi_word > 0) {
- masm->sll(loword, hiword, mantissa_shift_for_lo_word);
- masm->srl(hiword, hiword, mantissa_shift_for_hi_word);
+ masm->sll(loword, src, mantissa_shift_for_lo_word);
+ masm->srl(hiword, src, mantissa_shift_for_hi_word);
masm->Or(hiword, scratch, hiword);
} else {
masm->mov(loword, zero_reg);
- masm->sll(hiword, hiword, mantissa_shift_for_hi_word);
+ masm->sll(hiword, src, mantissa_shift_for_hi_word);
masm->Or(hiword, scratch, hiword);
}
@@ -4644,17 +4645,17 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr,
__ mtc1(src, dbl_scratch);
__ Cvt_d_uw(dbl_scratch, dbl_scratch, f22);
} else {
- Label no_leading_zero, done;
+ Label no_leading_zero, convert_done;
__ And(at, src, Operand(0x80000000));
__ Branch(&no_leading_zero, ne, at, Operand(zero_reg));
// Integer has one leading zeros.
- GenerateUInt2Double(masm(), sfpd_hi, sfpd_lo, t0, 1);
- __ Branch(&done);
+ GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, t0, 1);
+ __ Branch(&convert_done);
__ bind(&no_leading_zero);
- GenerateUInt2Double(masm(), sfpd_hi, sfpd_lo, t0, 0);
- __ Branch(&done);
+ GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, t0, 0);
+ __ bind(&convert_done);
}
}
@@ -5344,12 +5345,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
__ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
- __ AllocateInNewSpace(size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- flags);
+ __ Allocate(size,
+ result,
+ scratch,
+ scratch2,
+ deferred->entry(),
+ flags);
}
__ bind(deferred->exit());
@@ -5771,6 +5772,13 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(zero_reg);
final_branch_condition = eq;
+ } else if (type_name->Equals(heap()->symbol_string())) {
+ __ JumpIfSmi(input, false_label);
+ __ GetObjectType(input, input, scratch);
+ cmp1 = scratch;
+ cmp2 = Operand(SYMBOL_TYPE);
+ final_branch_condition = eq;
+
} else if (type_name->Equals(heap()->boolean_string())) {
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
@@ -5814,27 +5822,15 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ LoadRoot(at, Heap::kNullValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
}
- if (FLAG_harmony_symbols) {
- // input is an object, it is safe to use GetObjectType in the delay slot.
- __ GetObjectType(input, input, scratch);
- __ Branch(USE_DELAY_SLOT, true_label, eq, scratch, Operand(SYMBOL_TYPE));
- // Still an object, so the InstanceType can be loaded.
- __ lbu(scratch, FieldMemOperand(input, Map::kInstanceTypeOffset));
- __ Branch(USE_DELAY_SLOT, false_label,
- lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- } else {
- // input is an object, it is safe to use GetObjectType in the delay slot.
- __ GetObjectType(input, input, scratch);
- __ Branch(USE_DELAY_SLOT, false_label,
- lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- }
- // Still an object, so the InstanceType can be loaded.
- __ lbu(scratch, FieldMemOperand(input, Map::kInstanceTypeOffset));
+ Register map = input;
+ __ GetObjectType(input, map, scratch);
+ __ Branch(false_label,
+ lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ Branch(USE_DELAY_SLOT, false_label,
gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- // Still an object, so the BitField can be loaded.
+ // map is still valid, so the BitField can be loaded in delay slot.
// Check for undetectable objects => false.
- __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
+ __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
__ And(at, at, 1 << Map::kIsUndetectable);
cmp1 = at;
cmp2 = Operand(zero_reg);
diff --git a/deps/v8/src/mips/lithium-codegen-mips.h b/deps/v8/src/mips/lithium-codegen-mips.h
index 1d2a65912..bb2003f1d 100644
--- a/deps/v8/src/mips/lithium-codegen-mips.h
+++ b/deps/v8/src/mips/lithium-codegen-mips.h
@@ -87,6 +87,10 @@ class LCodeGen BASE_EMBEDDED {
return !NeedsEagerFrame() && info()->is_deferred_calling();
}
+ RAStatus GetRAState() const {
+ return frame_is_built_ ? kRAHasBeenSaved : kRAHasNotBeenSaved;
+ }
+
// Support for converting LOperands to assembler types.
// LOperand must be a register.
Register ToRegister(LOperand* op) const;
diff --git a/deps/v8/src/mips/lithium-mips.cc b/deps/v8/src/mips/lithium-mips.cc
index 8848032b6..652c7cad0 100644
--- a/deps/v8/src/mips/lithium-mips.cc
+++ b/deps/v8/src/mips/lithium-mips.cc
@@ -871,6 +871,35 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LInstruction* instr = current->CompileToLithium(this);
if (instr != NULL) {
+#if DEBUG
+ // Make sure that the lithium instruction has either no fixed register
+ // constraints in temps or the result OR no uses that are only used at
+ // start. If this invariant doesn't hold, the register allocator can decide
+ // to insert a split of a range immediately before the instruction due to an
+ // already allocated register needing to be used for the instruction's fixed
+ // register constraint. In this case, The register allocator won't see an
+ // interference between the split child and the use-at-start (it would if
+ // the it was just a plain use), so it is free to move the split child into
+ // the same register that is used for the use-at-start.
+ // See https://code.google.com/p/chromium/issues/detail?id=201590
+ if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
+ int fixed = 0;
+ int used_at_start = 0;
+ for (UseIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->IsUsedAtStart()) ++used_at_start;
+ }
+ if (instr->Output() != NULL) {
+ if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
+ }
+ for (TempIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->HasFixedPolicy()) ++fixed;
+ }
+ ASSERT(fixed == 0 || used_at_start == 0);
+ }
+#endif
+
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -1116,7 +1145,7 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
return DefineFixedDouble(result, f4);
} else {
- LOperand* input = UseRegisterAtStart(instr->value());
+ LOperand* input = UseRegister(instr->value());
LOperand* temp = (op == kMathRound) ? FixedTemp(f6) :
(op == kMathFloor) ? TempRegister() : NULL;
@@ -1585,12 +1614,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
-LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
- LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LJSArrayLength(array));
-}
-
-
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
@@ -1697,11 +1720,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
return AssignEnvironment(DefineAsRegister(res));
} else {
ASSERT(to.IsInteger32());
- LOperand* value = UseRegisterAtStart(instr->value());
+ LOperand* value = NULL;
LInstruction* res = NULL;
if (instr->value()->type().IsSmi()) {
+ value = UseRegisterAtStart(instr->value());
res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
} else {
+ value = UseRegister(instr->value());
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
@@ -2081,7 +2106,7 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind(
LOperand* new_map_reg = TempRegister();
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
- return DefineSameAsFirst(result);
+ return result;
} else if (FLAG_compiled_transitions) {
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, NULL, NULL);
diff --git a/deps/v8/src/mips/lithium-mips.h b/deps/v8/src/mips/lithium-mips.h
index 80635c389..e99590545 100644
--- a/deps/v8/src/mips/lithium-mips.h
+++ b/deps/v8/src/mips/lithium-mips.h
@@ -120,7 +120,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@@ -291,7 +290,6 @@ class LInstruction: public ZoneObject {
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
bool is_call_;
- bool is_save_doubles_;
};
@@ -1111,19 +1109,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
};
-class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LJSArrayLength(LOperand* value) {
- inputs_[0] = value;
- }
-
- LOperand* value() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
- DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
-};
-
-
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {
@@ -2060,7 +2045,7 @@ class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
};
-class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
+class LTransitionElementsKind: public LTemplateInstruction<0, 1, 2> {
public:
LTransitionElementsKind(LOperand* object,
LOperand* new_map_temp,
diff --git a/deps/v8/src/mips/macro-assembler-mips.cc b/deps/v8/src/mips/macro-assembler-mips.cc
index 603f1be70..12e102504 100644
--- a/deps/v8/src/mips/macro-assembler-mips.cc
+++ b/deps/v8/src/mips/macro-assembler-mips.cc
@@ -1108,6 +1108,7 @@ void MacroAssembler::BranchF(Label* target,
FPURegister cmp1,
FPURegister cmp2,
BranchDelaySlot bd) {
+ BlockTrampolinePoolScope block_trampoline_pool(this);
if (cc == al) {
Branch(bd, target);
return;
@@ -1700,6 +1701,7 @@ void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
if (rt.is_reg()) {
// NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or
// rt.
+ BlockTrampolinePoolScope block_trampoline_pool(this);
r2 = rt.rm_;
switch (cond) {
case cc_always:
@@ -1785,6 +1787,7 @@ void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
// Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching the
// target.
+ BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) {
case cc_always:
b(offset);
@@ -1925,10 +1928,11 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
BranchDelaySlot bdslot) {
BRANCH_ARGS_CHECK(cond, rs, rt);
- int32_t offset;
+ int32_t offset = 0;
Register r2 = no_reg;
Register scratch = at;
if (rt.is_reg()) {
+ BlockTrampolinePoolScope block_trampoline_pool(this);
r2 = rt.rm_;
// Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching the
@@ -2035,6 +2039,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
// Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching the
// target.
+ BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) {
case cc_always:
offset = shifted_branch_offset(L, false);
@@ -2271,67 +2276,70 @@ void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
li(r2, rt);
}
- switch (cond) {
- case cc_always:
- bal(offset);
- break;
- case eq:
- bne(rs, r2, 2);
- nop();
- bal(offset);
- break;
- case ne:
- beq(rs, r2, 2);
- nop();
- bal(offset);
- break;
+ {
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ switch (cond) {
+ case cc_always:
+ bal(offset);
+ break;
+ case eq:
+ bne(rs, r2, 2);
+ nop();
+ bal(offset);
+ break;
+ case ne:
+ beq(rs, r2, 2);
+ nop();
+ bal(offset);
+ break;
- // Signed comparison.
- case greater:
- slt(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- bgezal(scratch, offset);
- break;
- case greater_equal:
- slt(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- bltzal(scratch, offset);
- break;
- case less:
- slt(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- bgezal(scratch, offset);
- break;
- case less_equal:
- slt(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- bltzal(scratch, offset);
- break;
+ // Signed comparison.
+ case greater:
+ slt(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ bgezal(scratch, offset);
+ break;
+ case greater_equal:
+ slt(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ bltzal(scratch, offset);
+ break;
+ case less:
+ slt(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ bgezal(scratch, offset);
+ break;
+ case less_equal:
+ slt(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ bltzal(scratch, offset);
+ break;
- // Unsigned comparison.
- case Ugreater:
- sltu(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- bgezal(scratch, offset);
- break;
- case Ugreater_equal:
- sltu(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- bltzal(scratch, offset);
- break;
- case Uless:
- sltu(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- bgezal(scratch, offset);
- break;
- case Uless_equal:
- sltu(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- bltzal(scratch, offset);
- break;
+ // Unsigned comparison.
+ case Ugreater:
+ sltu(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ bgezal(scratch, offset);
+ break;
+ case Ugreater_equal:
+ sltu(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ bltzal(scratch, offset);
+ break;
+ case Uless:
+ sltu(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ bgezal(scratch, offset);
+ break;
+ case Uless_equal:
+ sltu(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ bltzal(scratch, offset);
+ break;
- default:
- UNREACHABLE();
+ default:
+ UNREACHABLE();
+ }
}
// Emit a nop in the branch delay slot if required.
if (bdslot == PROTECT)
@@ -2353,7 +2361,7 @@ void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
BranchDelaySlot bdslot) {
BRANCH_ARGS_CHECK(cond, rs, rt);
- int32_t offset;
+ int32_t offset = 0;
Register r2 = no_reg;
Register scratch = at;
if (rt.is_reg()) {
@@ -2363,80 +2371,82 @@ void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
li(r2, rt);
}
- switch (cond) {
- case cc_always:
- offset = shifted_branch_offset(L, false);
- bal(offset);
- break;
- case eq:
- bne(rs, r2, 2);
- nop();
- offset = shifted_branch_offset(L, false);
- bal(offset);
- break;
- case ne:
- beq(rs, r2, 2);
- nop();
- offset = shifted_branch_offset(L, false);
- bal(offset);
- break;
+ {
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ switch (cond) {
+ case cc_always:
+ offset = shifted_branch_offset(L, false);
+ bal(offset);
+ break;
+ case eq:
+ bne(rs, r2, 2);
+ nop();
+ offset = shifted_branch_offset(L, false);
+ bal(offset);
+ break;
+ case ne:
+ beq(rs, r2, 2);
+ nop();
+ offset = shifted_branch_offset(L, false);
+ bal(offset);
+ break;
- // Signed comparison.
- case greater:
- slt(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bgezal(scratch, offset);
- break;
- case greater_equal:
- slt(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bltzal(scratch, offset);
- break;
- case less:
- slt(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bgezal(scratch, offset);
- break;
- case less_equal:
- slt(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bltzal(scratch, offset);
- break;
+ // Signed comparison.
+ case greater:
+ slt(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bgezal(scratch, offset);
+ break;
+ case greater_equal:
+ slt(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bltzal(scratch, offset);
+ break;
+ case less:
+ slt(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bgezal(scratch, offset);
+ break;
+ case less_equal:
+ slt(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bltzal(scratch, offset);
+ break;
- // Unsigned comparison.
- case Ugreater:
- sltu(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bgezal(scratch, offset);
- break;
- case Ugreater_equal:
- sltu(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bltzal(scratch, offset);
- break;
- case Uless:
- sltu(scratch, rs, r2);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bgezal(scratch, offset);
- break;
- case Uless_equal:
- sltu(scratch, r2, rs);
- addiu(scratch, scratch, -1);
- offset = shifted_branch_offset(L, false);
- bltzal(scratch, offset);
- break;
+ // Unsigned comparison.
+ case Ugreater:
+ sltu(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bgezal(scratch, offset);
+ break;
+ case Ugreater_equal:
+ sltu(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bltzal(scratch, offset);
+ break;
+ case Uless:
+ sltu(scratch, rs, r2);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bgezal(scratch, offset);
+ break;
+ case Uless_equal:
+ sltu(scratch, r2, rs);
+ addiu(scratch, scratch, -1);
+ offset = shifted_branch_offset(L, false);
+ bltzal(scratch, offset);
+ break;
- default:
- UNREACHABLE();
+ default:
+ UNREACHABLE();
+ }
}
-
// Check that offset could actually hold on an int16_t.
ASSERT(is_int16(offset));
@@ -2992,13 +3002,12 @@ void MacroAssembler::Allocate(int object_size,
}
-void MacroAssembler::AllocateInNewSpace(Register object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags) {
- ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
+void MacroAssembler::Allocate(Register object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags) {
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -3019,19 +3028,19 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
// Check relative positions of allocation top and limit addresses.
// ARM adds additional checks to make sure the ldm instruction can be
// used. On MIPS we don't have ldm so we don't need additional checks either.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
intptr_t top =
- reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+ reinterpret_cast<intptr_t>(allocation_top.address());
intptr_t limit =
- reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+ reinterpret_cast<intptr_t>(allocation_limit.address());
ASSERT((limit - top) == kPointerSize);
// Set up allocation top address and object size registers.
Register topaddr = scratch1;
- li(topaddr, Operand(new_space_allocation_top));
+ li(topaddr, Operand(allocation_top));
// This code stores a temporary value in t9.
if ((flags & RESULT_CONTAINS_TOP) == 0) {
@@ -3110,12 +3119,12 @@ void MacroAssembler::AllocateTwoByteString(Register result,
And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
// Allocate two-byte string in new space.
- AllocateInNewSpace(scratch1,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(scratch1,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
InitializeNewString(result,
@@ -3140,12 +3149,12 @@ void MacroAssembler::AllocateAsciiString(Register result,
And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
// Allocate ASCII string in new space.
- AllocateInNewSpace(scratch1,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(scratch1,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
InitializeNewString(result,
@@ -5505,7 +5514,6 @@ bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
CodePatcher::CodePatcher(byte* address, int instructions)
: address_(address),
- instructions_(instructions),
size_(instructions * Assembler::kInstrSize),
masm_(NULL, address, size_ + Assembler::kGap) {
// Create a new macro assembler pointing to the address of the code to patch.
diff --git a/deps/v8/src/mips/macro-assembler-mips.h b/deps/v8/src/mips/macro-assembler-mips.h
index e4cf3bcb7..125cc8aaf 100644
--- a/deps/v8/src/mips/macro-assembler-mips.h
+++ b/deps/v8/src/mips/macro-assembler-mips.h
@@ -491,12 +491,12 @@ class MacroAssembler: public Assembler {
Label* gc_required,
AllocationFlags flags);
- void AllocateInNewSpace(Register object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(Register object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags);
// Undo allocation in new space. The object passed and objects allocated after
// it will no longer be allocated. The caller must make sure that no pointers
@@ -1565,7 +1565,6 @@ class CodePatcher {
private:
byte* address_; // The address of the code being patched.
- int instructions_; // Number of instructions of the expected patch size.
int size_; // Number of bytes of the expected patch size.
MacroAssembler masm_; // Macro assembler used to generate the code.
};
diff --git a/deps/v8/src/mips/regexp-macro-assembler-mips.cc b/deps/v8/src/mips/regexp-macro-assembler-mips.cc
index 036cbb13e..2fbc0eaa5 100644
--- a/deps/v8/src/mips/regexp-macro-assembler-mips.cc
+++ b/deps/v8/src/mips/regexp-macro-assembler-mips.cc
@@ -1005,6 +1005,7 @@ void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) {
int target = label->pos();
__ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag));
} else {
+ Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
Label after_constant;
__ Branch(&after_constant);
int offset = masm_->pc_offset();
diff --git a/deps/v8/src/mips/simulator-mips.cc b/deps/v8/src/mips/simulator-mips.cc
index be9f369d0..5eb79eb78 100644
--- a/deps/v8/src/mips/simulator-mips.cc
+++ b/deps/v8/src/mips/simulator-mips.cc
@@ -132,8 +132,8 @@ void MipsDebugger::Stop(Instruction* instr) {
ASSERT(msg != NULL);
// Update this stop description.
- if (!watched_stops[code].desc) {
- watched_stops[code].desc = msg;
+ if (!watched_stops_[code].desc) {
+ watched_stops_[code].desc = msg;
}
if (strlen(msg) > 0) {
@@ -163,8 +163,8 @@ void MipsDebugger::Stop(Instruction* instr) {
char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
Instruction::kInstrSize);
// Update this stop description.
- if (!sim_->watched_stops[code].desc) {
- sim_->watched_stops[code].desc = msg;
+ if (!sim_->watched_stops_[code].desc) {
+ sim_->watched_stops_[code].desc = msg;
}
PrintF("Simulator hit %s (%u)\n", msg, code);
sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
@@ -513,7 +513,7 @@ void MipsDebugger::Debug() {
int32_t words;
if (argc == next_arg) {
words = 10;
- } else if (argc == next_arg + 1) {
+ } else {
if (!GetValue(argv[next_arg], &words)) {
words = 10;
}
@@ -1636,33 +1636,33 @@ bool Simulator::IsStopInstruction(Instruction* instr) {
bool Simulator::IsEnabledStop(uint32_t code) {
ASSERT(code <= kMaxStopCode);
ASSERT(code > kMaxWatchpointCode);
- return !(watched_stops[code].count & kStopDisabledBit);
+ return !(watched_stops_[code].count & kStopDisabledBit);
}
void Simulator::EnableStop(uint32_t code) {
if (!IsEnabledStop(code)) {
- watched_stops[code].count &= ~kStopDisabledBit;
+ watched_stops_[code].count &= ~kStopDisabledBit;
}
}
void Simulator::DisableStop(uint32_t code) {
if (IsEnabledStop(code)) {
- watched_stops[code].count |= kStopDisabledBit;
+ watched_stops_[code].count |= kStopDisabledBit;
}
}
void Simulator::IncreaseStopCounter(uint32_t code) {
ASSERT(code <= kMaxStopCode);
- if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
+ if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
PrintF("Stop counter for code %i has overflowed.\n"
"Enabling this code and reseting the counter to 0.\n", code);
- watched_stops[code].count = 0;
+ watched_stops_[code].count = 0;
EnableStop(code);
} else {
- watched_stops[code].count++;
+ watched_stops_[code].count++;
}
}
@@ -1677,12 +1677,12 @@ void Simulator::PrintStopInfo(uint32_t code) {
return;
}
const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
- int32_t count = watched_stops[code].count & ~kStopDisabledBit;
+ int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
// Don't print the state of unused breakpoints.
if (count != 0) {
- if (watched_stops[code].desc) {
+ if (watched_stops_[code].desc) {
PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
- code, code, state, count, watched_stops[code].desc);
+ code, code, state, count, watched_stops_[code].desc);
} else {
PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
code, code, state, count);
diff --git a/deps/v8/src/mips/simulator-mips.h b/deps/v8/src/mips/simulator-mips.h
index 67f595302..ed6344342 100644
--- a/deps/v8/src/mips/simulator-mips.h
+++ b/deps/v8/src/mips/simulator-mips.h
@@ -391,14 +391,14 @@ class Simulator {
static const uint32_t kStopDisabledBit = 1 << 31;
// A stop is enabled, meaning the simulator will stop when meeting the
- // instruction, if bit 31 of watched_stops[code].count is unset.
- // The value watched_stops[code].count & ~(1 << 31) indicates how many times
+ // instruction, if bit 31 of watched_stops_[code].count is unset.
+ // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
// the breakpoint was hit or gone through.
struct StopCountAndDesc {
uint32_t count;
char* desc;
};
- StopCountAndDesc watched_stops[kMaxStopCode + 1];
+ StopCountAndDesc watched_stops_[kMaxStopCode + 1];
};
diff --git a/deps/v8/src/mips/stub-cache-mips.cc b/deps/v8/src/mips/stub-cache-mips.cc
index d5cf6de90..da6770a14 100644
--- a/deps/v8/src/mips/stub-cache-mips.cc
+++ b/deps/v8/src/mips/stub-cache-mips.cc
@@ -415,7 +415,7 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
// may be clobbered.
void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
@@ -428,16 +428,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// a0 : value.
Label exit;
- LookupResult lookup(masm->isolate());
- object->Lookup(*name, &lookup);
- if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
- // In sloppy mode, we could just return the value and be done. However, we
- // might be in strict mode, where we have to throw. Since we cannot tell,
- // go into slow case unconditionally.
- __ jmp(miss_label);
- return;
- }
-
// Check that the map of the object hasn't changed.
CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
: REQUIRE_EXACT_MAP;
@@ -452,8 +442,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Check that we are allowed to write this.
if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
JSObject* holder;
- if (lookup.IsFound()) {
- holder = lookup.holder();
+ // holder == object indicates that no property was found.
+ if (lookup->holder() != *object) {
+ holder = lookup->holder();
} else {
// Find the top object.
holder = *object;
@@ -461,8 +452,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject());
}
- CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, miss_restore_name);
+ Register holder_reg = CheckPrototypes(
+ object, receiver_reg, Handle<JSObject>(holder), name_reg,
+ scratch1, scratch2, name, miss_restore_name);
+ // If no property was found, and the holder (the last object in the
+ // prototype chain) is in slow mode, we need to do a negative lookup on the
+ // holder.
+ if (lookup->holder() == *object &&
+ !holder->HasFastProperties() &&
+ !holder->IsJSGlobalProxy() &&
+ !holder->IsJSGlobalObject()) {
+ GenerateDictionaryNegativeLookup(
+ masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
+ }
}
// Stub never generated for non-global objects that require access
@@ -483,6 +485,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
return;
}
+ int index;
if (!transition.is_null()) {
// Update the map of the object.
__ li(scratch1, Operand(transition));
@@ -498,6 +501,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kDontSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
+ index = transition->instance_descriptors()->GetFieldIndex(
+ transition->LastAdded());
+ } else {
+ index = lookup->GetFieldIndex().field_index();
}
// Adjust for the number of properties stored in the object. Even in the
@@ -2424,6 +2431,12 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
// Check that the object is a symbol.
__ GetObjectType(a1, a1, a3);
__ Branch(&miss, ne, a3, Operand(SYMBOL_TYPE));
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::SYMBOL_FUNCTION_INDEX, a0, &miss);
+ CheckPrototypes(
+ Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
+ a0, holder, a3, a1, t0, name, &miss);
break;
case NUMBER_CHECK: {
@@ -3010,7 +3023,7 @@ Handle<Code> ConstructStubCompiler::CompileConstructStub(
__ Check(eq, "Instance size of initial map changed.",
a3, Operand(instance_size >> kPointerSizeLog2));
#endif
- __ AllocateInNewSpace(a3, t4, t5, t6, &generic_stub_call, SIZE_IN_WORDS);
+ __ Allocate(a3, t4, t5, t6, &generic_stub_call, SIZE_IN_WORDS);
// Allocated the JSObject, now initialize the fields. Map is set to initial
// map and properties and elements are set to empty fixed array.
diff --git a/deps/v8/src/mirror-debugger.js b/deps/v8/src/mirror-debugger.js
index 7f1a05aed..e1fd872f3 100644
--- a/deps/v8/src/mirror-debugger.js
+++ b/deps/v8/src/mirror-debugger.js
@@ -638,7 +638,7 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
// Find all the named properties.
if (kind & PropertyKind.Named) {
// Get the local property names.
- propertyNames = %GetLocalPropertyNames(this.value_);
+ propertyNames = %GetLocalPropertyNames(this.value_, true);
total += propertyNames.length;
// Get names for named interceptor properties if any.
diff --git a/deps/v8/src/object-observe.js b/deps/v8/src/object-observe.js
index b35f547ed..bfb4a6545 100644
--- a/deps/v8/src/object-observe.js
+++ b/deps/v8/src/object-observe.js
@@ -117,6 +117,9 @@ function ObjectUnobserve(object, callback) {
}
function EnqueueChangeRecord(changeRecord, observers) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(changeRecord.name)) return;
+
for (var i = 0; i < observers.length; i++) {
var observer = observers[i];
var observerInfo = observerInfoMap.get(observer);
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
index 82a71a5ff..44cab53cc 100644
--- a/deps/v8/src/objects-debug.cc
+++ b/deps/v8/src/objects-debug.cc
@@ -195,6 +195,9 @@ void HeapObject::HeapObjectVerify() {
case JS_MESSAGE_OBJECT_TYPE:
JSMessageObject::cast(this)->JSMessageObjectVerify();
break;
+ case JS_ARRAY_BUFFER_TYPE:
+ JSArrayBuffer::cast(this)->JSArrayBufferVerify();
+ break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
@@ -220,6 +223,7 @@ void Symbol::SymbolVerify() {
CHECK(IsSymbol());
CHECK(HasHashCode());
CHECK_GT(Hash(), 0);
+ CHECK(name()->IsUndefined() || name()->IsString());
}
@@ -711,6 +715,14 @@ void JSFunctionProxy::JSFunctionProxyVerify() {
VerifyPointer(construct_trap());
}
+void JSArrayBuffer::JSArrayBufferVerify() {
+ CHECK(IsJSArrayBuffer());
+ JSObjectVerify();
+ VerifyPointer(byte_length());
+ CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
+ || byte_length()->IsUndefined());
+}
+
void Foreign::ForeignVerify() {
CHECK(IsForeign());
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index 02542612b..ec03405fd 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -674,6 +674,7 @@ bool Object::IsBoolean() {
TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
+TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
@@ -1490,13 +1491,17 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* map) {
bool JSObject::TryTransitionToField(Handle<JSObject> object,
Handle<Name> key) {
if (!object->map()->HasTransitionArray()) return false;
- Handle<TransitionArray> transitions(object->map()->transitions());
- int transition = transitions->Search(*key);
- if (transition == TransitionArray::kNotFound) return false;
- PropertyDetails target_details = transitions->GetTargetDetails(transition);
- if (target_details.type() != FIELD) return false;
- if (target_details.attributes() != NONE) return false;
- Handle<Map> target(transitions->GetTarget(transition));
+ Handle<Map> target;
+ {
+ AssertNoAllocation no_allocation;
+ TransitionArray* transitions = object->map()->transitions();
+ int transition = transitions->Search(*key);
+ if (transition == TransitionArray::kNotFound) return false;
+ PropertyDetails target_details = transitions->GetTargetDetails(transition);
+ if (target_details.type() != FIELD) return false;
+ if (target_details.attributes() != NONE) return false;
+ target = Handle<Map>(transitions->GetTarget(transition));
+ }
JSObject::AddFastPropertyUsingMap(object, target);
return true;
}
@@ -1558,6 +1563,8 @@ int JSObject::GetHeaderSize() {
return JSDate::kSize;
case JS_ARRAY_TYPE:
return JSArray::kSize;
+ case JS_ARRAY_BUFFER_TYPE:
+ return JSArrayBuffer::kSize;
case JS_SET_TYPE:
return JSSet::kSize;
case JS_MAP_TYPE:
@@ -2444,6 +2451,7 @@ CAST_ACCESSOR(JSGlobalObject)
CAST_ACCESSOR(JSBuiltinsObject)
CAST_ACCESSOR(Code)
CAST_ACCESSOR(JSArray)
+CAST_ACCESSOR(JSArrayBuffer)
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSFunctionProxy)
@@ -2500,11 +2508,17 @@ void Name::set_hash_field(uint32_t value) {
bool Name::Equals(Name* other) {
if (other == this) return true;
- if (this->IsUniqueName() && other->IsUniqueName()) return false;
+ if (this->IsSymbol() || other->IsSymbol() ||
+ (this->IsInternalizedString() && other->IsInternalizedString())) {
+ return false;
+ }
return String::cast(this)->SlowEquals(String::cast(other));
}
+ACCESSORS(Symbol, name, Object, kNameOffset)
+
+
bool String::Equals(String* other) {
if (other == this) return true;
if (this->IsInternalizedString() && other->IsInternalizedString()) {
@@ -4125,9 +4139,12 @@ TransitionArray* Map::transitions() {
void Map::set_transitions(TransitionArray* transition_array,
WriteBarrierMode mode) {
- // In release mode, only run this code if verify_heap is on.
- if (Heap::ShouldZapGarbage() && HasTransitionArray()) {
- CHECK(transitions() != transition_array);
+ // Transition arrays are not shared. When one is replaced, it should not
+ // keep referenced objects alive, so we zap it.
+ // When there is another reference to the array somewhere (e.g. a handle),
+ // not zapping turns from a waste of memory into a source of crashes.
+ if (HasTransitionArray()) {
+ ASSERT(transitions() != transition_array);
ZapTransitions();
}
@@ -4505,6 +4522,7 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
kDontOptimize)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
void SharedFunctionInfo::BeforeVisitingPointers() {
if (IsInobjectSlackTrackingInProgress()) DetachInitialMap();
@@ -5121,6 +5139,21 @@ bool Code::contains(byte* inner_pointer) {
ACCESSORS(JSArray, length, Object, kLengthOffset)
+void* JSArrayBuffer::backing_store() {
+ intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
+ return reinterpret_cast<void*>(ptr);
+}
+
+
+void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
+ intptr_t ptr = reinterpret_cast<intptr_t>(value);
+ WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
+}
+
+
+ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
+
+
ACCESSORS(JSRegExp, data, Object, kDataOffset)
diff --git a/deps/v8/src/objects-printer.cc b/deps/v8/src/objects-printer.cc
index 4522ee43e..834223261 100644
--- a/deps/v8/src/objects-printer.cc
+++ b/deps/v8/src/objects-printer.cc
@@ -184,6 +184,8 @@ void HeapObject::HeapObjectPrint(FILE* out) {
case JS_GLOBAL_PROPERTY_CELL_TYPE:
JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
break;
+ case JS_ARRAY_BUFFER_TYPE:
+ JSArrayBuffer::cast(this)->JSArrayBufferPrint(out);
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
Name::cast(this)->Name##Print(out); \
@@ -552,6 +554,9 @@ static const char* TypeToString(InstanceType type) {
void Symbol::SymbolPrint(FILE* out) {
HeapObject::PrintHeader(out, "Symbol");
PrintF(out, " - hash: %d\n", Hash());
+ PrintF(out, " - name: ");
+ name()->ShortPrint();
+ PrintF(out, "\n");
}
@@ -792,6 +797,16 @@ void JSWeakMap::JSWeakMapPrint(FILE* out) {
}
+void JSArrayBuffer::JSArrayBufferPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSArrayBuffer");
+ PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - backing_store = -0x%p\n", backing_store());
+ PrintF(out, " - byte_length = ");
+ byte_length()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
void JSFunction::JSFunctionPrint(FILE* out) {
HeapObject::PrintHeader(out, "Function");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
diff --git a/deps/v8/src/objects-visiting-inl.h b/deps/v8/src/objects-visiting-inl.h
index beb07b564..6a64cbf80 100644
--- a/deps/v8/src/objects-visiting-inl.h
+++ b/deps/v8/src/objects-visiting-inl.h
@@ -49,6 +49,11 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
SlicedString::BodyDescriptor,
int>::Visit);
+ table_.Register(kVisitSymbol,
+ &FixedBodyVisitor<StaticVisitor,
+ Symbol::BodyDescriptor,
+ int>::Visit);
+
table_.Register(kVisitFixedArray,
&FlexibleBodyVisitor<StaticVisitor,
FixedArray::BodyDescriptor,
@@ -110,6 +115,11 @@ void StaticMarkingVisitor<StaticVisitor>::Initialize() {
SlicedString::BodyDescriptor,
void>::Visit);
+ table_.Register(kVisitSymbol,
+ &FixedBodyVisitor<StaticVisitor,
+ Symbol::BodyDescriptor,
+ void>::Visit);
+
table_.Register(kVisitFixedArray, &FixedArrayVisitor::Visit);
table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit);
@@ -397,7 +407,7 @@ void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(
}
// Since descriptor arrays are potentially shared, ensure that only the
- // descriptors that appeared for this map are marked. The first time a
+ // descriptors that belong to this map are marked. The first time a
// non-empty descriptor array is marked, its header is also visited. The slot
// holding the descriptor array will be implicitly recorded when the pointer
// fields of this map are visited.
@@ -410,13 +420,6 @@ void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(
}
int start = 0;
int end = map->NumberOfOwnDescriptors();
- Object* back_pointer = map->GetBackPointer();
- if (!back_pointer->IsUndefined()) {
- Map* parent_map = Map::cast(back_pointer);
- if (descriptors == parent_map->instance_descriptors()) {
- start = parent_map->NumberOfOwnDescriptors();
- }
- }
if (start < end) {
StaticVisitor::VisitPointers(heap,
descriptors->GetDescriptorStartSlot(start),
diff --git a/deps/v8/src/objects-visiting.cc b/deps/v8/src/objects-visiting.cc
index 088f5ebde..fa53562bd 100644
--- a/deps/v8/src/objects-visiting.cc
+++ b/deps/v8/src/objects-visiting.cc
@@ -129,9 +129,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
Foreign::kSize);
case SYMBOL_TYPE:
- return GetVisitorIdForSize(kVisitDataObject,
- kVisitDataObjectGeneric,
- Symbol::kSize);
+ return kVisitSymbol;
case FILLER_TYPE:
return kVisitDataObjectGeneric;
@@ -146,6 +144,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
+ case JS_ARRAY_BUFFER_TYPE:
return GetVisitorIdForSize(kVisitJSObject,
kVisitJSObjectGeneric,
instance_size);
diff --git a/deps/v8/src/objects-visiting.h b/deps/v8/src/objects-visiting.h
index 9b2422ca2..d4a2ed2d1 100644
--- a/deps/v8/src/objects-visiting.h
+++ b/deps/v8/src/objects-visiting.h
@@ -84,6 +84,7 @@ class StaticVisitorBase : public AllStatic {
V(StructGeneric) \
V(ConsString) \
V(SlicedString) \
+ V(Symbol) \
V(Oddball) \
V(Code) \
V(Map) \
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 00d00d5ee..8f03b1043 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -98,6 +98,10 @@ MaybeObject* Object::ToObject() {
Isolate* isolate = HeapObject::cast(this)->GetIsolate();
Context* native_context = isolate->context()->native_context();
return CreateJSValue(native_context->string_function(), this);
+ } else if (IsSymbol()) {
+ Isolate* isolate = HeapObject::cast(this)->GetIsolate();
+ Context* native_context = isolate->context()->native_context();
+ return CreateJSValue(native_context->symbol_function(), this);
}
// Throw a type error.
@@ -126,10 +130,10 @@ void Object::Lookup(Name* name, LookupResult* result) {
holder = native_context->number_function()->instance_prototype();
} else if (IsString()) {
holder = native_context->string_function()->instance_prototype();
+ } else if (IsSymbol()) {
+ holder = native_context->symbol_function()->instance_prototype();
} else if (IsBoolean()) {
holder = native_context->boolean_function()->instance_prototype();
- } else if (IsSymbol()) {
- holder = native_context->symbol_delegate();
} else {
Isolate::Current()->PushStackTraceAndDie(
0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
@@ -375,6 +379,9 @@ MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
Handle<Object> receiver(receiver_raw, isolate);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return isolate->heap()->undefined_value();
+
Handle<Object> args[] = { receiver, name };
Handle<Object> result = CallTrap(
"get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
@@ -756,7 +763,7 @@ MaybeObject* Object::GetProperty(Object* receiver,
// holder in the prototype chain.
// Proxy handlers do not use the proxy's prototype, so we can skip this.
if (!result->IsHandler()) {
- Object* last = result->IsProperty() && !receiver->IsSymbol()
+ Object* last = result->IsProperty()
? result->holder()
: Object::cast(heap->null_value());
ASSERT(this != this->GetPrototype(isolate));
@@ -837,10 +844,10 @@ MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
holder = native_context->number_function()->instance_prototype();
} else if (holder->IsString()) {
holder = native_context->string_function()->instance_prototype();
+ } else if (holder->IsSymbol()) {
+ holder = native_context->symbol_function()->instance_prototype();
} else if (holder->IsBoolean()) {
holder = native_context->boolean_function()->instance_prototype();
- } else if (holder->IsSymbol()) {
- holder = native_context->symbol_delegate();
} else if (holder->IsJSProxy()) {
return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
} else {
@@ -900,6 +907,9 @@ Object* Object::GetPrototype(Isolate* isolate) {
if (heap_object->IsString()) {
return context->string_function()->instance_prototype();
}
+ if (heap_object->IsSymbol()) {
+ return context->symbol_function()->instance_prototype();
+ }
if (heap_object->IsBoolean()) {
return context->boolean_function()->instance_prototype();
} else {
@@ -908,16 +918,6 @@ Object* Object::GetPrototype(Isolate* isolate) {
}
-Object* Object::GetDelegate(Isolate* isolate) {
- if (IsSymbol()) {
- Heap* heap = Symbol::cast(this)->GetHeap();
- Context* context = heap->isolate()->context()->native_context();
- return context->symbol_delegate();
- }
- return GetPrototype(isolate);
-}
-
-
MaybeObject* Object::GetHash(CreationFlag flag) {
// The object is either a number, a name, an odd-ball,
// a real JS object, or a Harmony proxy.
@@ -1467,9 +1467,16 @@ void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
accumulator->Add("<Odd Oddball>");
break;
}
- case SYMBOL_TYPE:
- accumulator->Add("<Symbol: %d>", Symbol::cast(this)->Hash());
+ case SYMBOL_TYPE: {
+ Symbol* symbol = Symbol::cast(this);
+ accumulator->Add("<Symbol: %d", symbol->Hash());
+ if (!symbol->name()->IsUndefined()) {
+ accumulator->Add(" ");
+ String::cast(symbol->name())->StringShortPrint(accumulator);
+ }
+ accumulator->Add(">");
break;
+ }
case HEAP_NUMBER_TYPE:
accumulator->Add("<Number: ");
HeapNumber::cast(this)->HeapNumberPrint(accumulator);
@@ -1543,6 +1550,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_VALUE_TYPE:
case JS_DATE_TYPE:
case JS_ARRAY_TYPE:
+ case JS_ARRAY_BUFFER_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_WEAK_MAP_TYPE:
@@ -1579,6 +1587,8 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
break;
case SYMBOL_TYPE:
+ Symbol::BodyDescriptor::IterateBody(this, v);
+ break;
case HEAP_NUMBER_TYPE:
case FILLER_TYPE:
case BYTE_ARRAY_TYPE:
@@ -1728,7 +1738,7 @@ MaybeObject* JSObject::AddFastProperty(Name* name,
// hidden strings) and is not a real identifier.
// Normalize the object if it will have too many fast properties.
Isolate* isolate = GetHeap()->isolate();
- if ((!IsIdentifier(isolate->unicode_cache(), name)
+ if ((!name->IsSymbol() && !IsIdentifier(isolate->unicode_cache(), name)
&& name != isolate->heap()->hidden_string()) ||
(map()->unused_property_fields() == 0 &&
TooManyFastProperties(properties()->length(), store_mode))) {
@@ -2755,6 +2765,9 @@ bool JSProxy::HasPropertyWithHandler(Name* name_raw) {
Handle<Object> receiver(this, isolate);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return false;
+
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
@@ -2776,6 +2789,9 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
Handle<Object> name(name_raw, isolate);
Handle<Object> value(value_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return *value;
+
Handle<Object> args[] = { receiver, name, value };
CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
if (isolate->has_pending_exception()) return Failure::Exception();
@@ -2798,6 +2814,12 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
Handle<Object> value(value_raw, isolate);
Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy.
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) {
+ *done = false;
+ return isolate->heap()->the_hole_value();
+ }
+
*done = true; // except where redefined...
Handle<Object> args[] = { name };
Handle<Object> result = proxy->CallTrap(
@@ -2806,7 +2828,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
if (result->IsUndefined()) {
*done = false;
- return GetHeap()->the_hole_value();
+ return isolate->heap()->the_hole_value();
}
// Emulate [[GetProperty]] semantics for proxies.
@@ -2887,6 +2909,9 @@ MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
Handle<JSProxy> receiver(this);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return isolate->heap()->false_value();
+
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"delete", Handle<Object>(), ARRAY_SIZE(args), args);
@@ -2927,6 +2952,9 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
Handle<JSReceiver> receiver(receiver_raw);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return ABSENT;
+
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
@@ -4665,6 +4693,145 @@ MaybeObject* JSObject::PreventExtensions() {
}
+MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
+ StackLimitCheck check(isolate);
+ if (check.HasOverflowed()) return isolate->StackOverflow();
+
+ Heap* heap = isolate->heap();
+ Object* result;
+ { MaybeObject* maybe_result = heap->CopyJSObject(this);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ JSObject* copy = JSObject::cast(result);
+
+ // Deep copy local properties.
+ if (copy->HasFastProperties()) {
+ FixedArray* properties = copy->properties();
+ for (int i = 0; i < properties->length(); i++) {
+ Object* value = properties->get(i);
+ if (value->IsJSObject()) {
+ JSObject* js_object = JSObject::cast(value);
+ { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ properties->set(i, result);
+ }
+ }
+ int nof = copy->map()->inobject_properties();
+ for (int i = 0; i < nof; i++) {
+ Object* value = copy->InObjectPropertyAt(i);
+ if (value->IsJSObject()) {
+ JSObject* js_object = JSObject::cast(value);
+ { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ copy->InObjectPropertyAtPut(i, result);
+ }
+ }
+ } else {
+ { MaybeObject* maybe_result =
+ heap->AllocateFixedArray(copy->NumberOfLocalProperties());
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ FixedArray* names = FixedArray::cast(result);
+ copy->GetLocalPropertyNames(names, 0);
+ for (int i = 0; i < names->length(); i++) {
+ ASSERT(names->get(i)->IsString());
+ String* key_string = String::cast(names->get(i));
+ PropertyAttributes attributes =
+ copy->GetLocalPropertyAttribute(key_string);
+ // Only deep copy fields from the object literal expression.
+ // In particular, don't try to copy the length attribute of
+ // an array.
+ if (attributes != NONE) continue;
+ Object* value =
+ copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
+ if (value->IsJSObject()) {
+ JSObject* js_object = JSObject::cast(value);
+ { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ { MaybeObject* maybe_result =
+ // Creating object copy for literals. No strict mode needed.
+ copy->SetProperty(key_string, result, NONE, kNonStrictMode);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ }
+ }
+ }
+
+ // Deep copy local elements.
+ // Pixel elements cannot be created using an object literal.
+ ASSERT(!copy->HasExternalArrayElements());
+ switch (copy->GetElementsKind()) {
+ case FAST_SMI_ELEMENTS:
+ case FAST_ELEMENTS:
+ case FAST_HOLEY_SMI_ELEMENTS:
+ case FAST_HOLEY_ELEMENTS: {
+ FixedArray* elements = FixedArray::cast(copy->elements());
+ if (elements->map() == heap->fixed_cow_array_map()) {
+ isolate->counters()->cow_arrays_created_runtime()->Increment();
+#ifdef DEBUG
+ for (int i = 0; i < elements->length(); i++) {
+ ASSERT(!elements->get(i)->IsJSObject());
+ }
+#endif
+ } else {
+ for (int i = 0; i < elements->length(); i++) {
+ Object* value = elements->get(i);
+ ASSERT(value->IsSmi() ||
+ value->IsTheHole() ||
+ (IsFastObjectElementsKind(copy->GetElementsKind())));
+ if (value->IsJSObject()) {
+ JSObject* js_object = JSObject::cast(value);
+ { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ elements->set(i, result);
+ }
+ }
+ }
+ break;
+ }
+ case DICTIONARY_ELEMENTS: {
+ SeededNumberDictionary* element_dictionary = copy->element_dictionary();
+ int capacity = element_dictionary->Capacity();
+ for (int i = 0; i < capacity; i++) {
+ Object* k = element_dictionary->KeyAt(i);
+ if (element_dictionary->IsKey(k)) {
+ Object* value = element_dictionary->ValueAt(i);
+ if (value->IsJSObject()) {
+ JSObject* js_object = JSObject::cast(value);
+ { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ element_dictionary->ValueAtPut(i, result);
+ }
+ }
+ }
+ break;
+ }
+ case NON_STRICT_ARGUMENTS_ELEMENTS:
+ UNIMPLEMENTED();
+ break;
+ case EXTERNAL_PIXEL_ELEMENTS:
+ case EXTERNAL_BYTE_ELEMENTS:
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case EXTERNAL_SHORT_ELEMENTS:
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case EXTERNAL_INT_ELEMENTS:
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case EXTERNAL_FLOAT_ELEMENTS:
+ case EXTERNAL_DOUBLE_ELEMENTS:
+ case FAST_DOUBLE_ELEMENTS:
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
+ // No contained objects, nothing to do.
+ break;
+ }
+ return copy;
+}
+
+
// Tests for the fast common case for property enumeration:
// - This object and all prototypes has an enum cache (which means that
// it is no proxy, has no interceptors and needs no access checks).
@@ -7626,33 +7793,45 @@ bool String::SlowAsArrayIndex(uint32_t* index) {
}
-String* SeqString::Truncate(int new_length) {
- Heap* heap = GetHeap();
- if (new_length <= 0) return heap->empty_string();
-
- int string_size, allocated_string_size;
- int old_length = length();
- if (old_length <= new_length) return this;
+Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
+ int new_size, old_size;
+ int old_length = string->length();
+ if (old_length <= new_length) return string;
- if (IsSeqOneByteString()) {
- allocated_string_size = SeqOneByteString::SizeFor(old_length);
- string_size = SeqOneByteString::SizeFor(new_length);
+ if (string->IsSeqOneByteString()) {
+ old_size = SeqOneByteString::SizeFor(old_length);
+ new_size = SeqOneByteString::SizeFor(new_length);
} else {
- allocated_string_size = SeqTwoByteString::SizeFor(old_length);
- string_size = SeqTwoByteString::SizeFor(new_length);
+ ASSERT(string->IsSeqTwoByteString());
+ old_size = SeqTwoByteString::SizeFor(old_length);
+ new_size = SeqTwoByteString::SizeFor(new_length);
}
- int delta = allocated_string_size - string_size;
- set_length(new_length);
+ int delta = old_size - new_size;
+ string->set_length(new_length);
- // String sizes are pointer size aligned, so that we can use filler objects
- // that are a multiple of pointer size.
- Address end_of_string = address() + string_size;
- heap->CreateFillerObjectAt(end_of_string, delta);
- if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
- MemoryChunk::IncrementLiveBytesFromMutator(address(), -delta);
+ Address start_of_string = string->address();
+ ASSERT_OBJECT_ALIGNED(start_of_string);
+ ASSERT_OBJECT_ALIGNED(start_of_string + new_size);
+
+ Heap* heap = string->GetHeap();
+ NewSpace* newspace = heap->new_space();
+ if (newspace->Contains(start_of_string) &&
+ newspace->top() == start_of_string + old_size) {
+ // Last allocated object in new space. Simply lower allocation top.
+ *(newspace->allocation_top_address()) = start_of_string + new_size;
+ } else {
+ // Sizes are pointer size aligned, so that we can use filler objects
+ // that are a multiple of pointer size.
+ heap->CreateFillerObjectAt(start_of_string + new_size, delta);
}
- return this;
+ if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) {
+ MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta);
+ }
+
+
+ if (new_length == 0) return heap->isolate()->factory()->empty_string();
+ return string;
}
@@ -8813,19 +8992,13 @@ void Code::CopyFrom(const CodeDesc& desc) {
ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
// copy code
- CHECK(IsCode());
- CHECK(relocation_info()->IsByteArray());
- CHECK(reinterpret_cast<intptr_t>(instruction_start()) ==
- reinterpret_cast<intptr_t>(this) + Code::kHeaderSize - kHeapObjectTag);
- memmove(instruction_start(), desc.buffer, desc.instr_size);
+ CopyBytes(instruction_start(), desc.buffer,
+ static_cast<size_t>(desc.instr_size));
// copy reloc info
- // TODO(mstarzinger): Remove once we found the bug.
- CHECK(IsCode());
- CHECK(relocation_info()->IsByteArray());
- memmove(relocation_start(),
- desc.buffer + desc.buffer_size - desc.reloc_size,
- desc.reloc_size);
+ CopyBytes(relocation_start(),
+ desc.buffer + desc.buffer_size - desc.reloc_size,
+ static_cast<size_t>(desc.reloc_size));
// unbox handles and relocate
intptr_t delta = instruction_start() - desc.buffer;
@@ -9758,9 +9931,14 @@ MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
void Map::ZapTransitions() {
TransitionArray* transition_array = transitions();
- MemsetPointer(transition_array->data_start(),
- GetHeap()->the_hole_value(),
- transition_array->length());
+ // TODO(mstarzinger): Temporarily use a slower version instead of the faster
+ // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
+ Object** data = transition_array->data_start();
+ Object* the_hole = GetHeap()->the_hole_value();
+ int length = transition_array->length();
+ for (int i = 0; i < length; i++) {
+ data[i] = the_hole;
+ }
}
@@ -11593,18 +11771,22 @@ void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
// Fill in the names of local properties into the supplied storage. The main
// purpose of this function is to provide reflection information for the object
// mirrors.
-void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
- ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
+void JSObject::GetLocalPropertyNames(
+ FixedArray* storage, int index, PropertyAttributes filter) {
+ ASSERT(storage->length() >= (NumberOfLocalProperties(filter) - index));
if (HasFastProperties()) {
int real_size = map()->NumberOfOwnDescriptors();
DescriptorArray* descs = map()->instance_descriptors();
- ASSERT(storage->length() >= index + real_size);
for (int i = 0; i < real_size; i++) {
- storage->set(index + i, descs->GetKey(i));
+ if ((descs->GetDetails(i).attributes() & filter) == 0 &&
+ ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
+ storage->set(index++, descs->GetKey(i));
+ }
}
} else {
property_dictionary()->CopyKeysTo(storage,
index,
+ filter,
NameDictionary::UNSORTED);
}
}
@@ -12355,6 +12537,7 @@ template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
template void Dictionary<NameDictionaryShape, Name*>::CopyKeysTo(
FixedArray*,
int,
+ PropertyAttributes,
Dictionary<NameDictionaryShape, Name*>::SortMode);
template int
@@ -13597,6 +13780,7 @@ template<typename Shape, typename Key>
void Dictionary<Shape, Key>::CopyKeysTo(
FixedArray* storage,
int index,
+ PropertyAttributes filter,
typename Dictionary<Shape, Key>::SortMode sort_mode) {
ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
static_cast<PropertyAttributes>(NONE)));
@@ -13606,7 +13790,8 @@ void Dictionary<Shape, Key>::CopyKeysTo(
if (HashTable<Shape, Key>::IsKey(k)) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
- storage->set(index++, k);
+ PropertyAttributes attr = details.attributes();
+ if ((attr & filter) == 0) storage->set(index++, k);
}
}
if (sort_mode == Dictionary<Shape, Key>::SORTED) {
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 933a07599..37be25f88 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -56,6 +56,7 @@
// - JSReceiver (suitable for property access)
// - JSObject
// - JSArray
+// - JSArrayBuffer
// - JSSet
// - JSMap
// - JSWeakMap
@@ -399,6 +400,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
V(JS_BUILTINS_OBJECT_TYPE) \
V(JS_GLOBAL_PROXY_TYPE) \
V(JS_ARRAY_TYPE) \
+ V(JS_ARRAY_BUFFER_TYPE) \
V(JS_PROXY_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_REGEXP_TYPE) \
@@ -729,6 +731,7 @@ enum InstanceType {
JS_BUILTINS_OBJECT_TYPE,
JS_GLOBAL_PROXY_TYPE,
JS_ARRAY_TYPE,
+ JS_ARRAY_BUFFER_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
JS_WEAK_MAP_TYPE,
@@ -974,6 +977,7 @@ class MaybeObject BASE_EMBEDDED {
V(Foreign) \
V(Boolean) \
V(JSArray) \
+ V(JSArrayBuffer) \
V(JSProxy) \
V(JSFunctionProxy) \
V(JSSet) \
@@ -1102,9 +1106,6 @@ class Object : public MaybeObject {
// Return the object's prototype (might be Heap::null_value()).
Object* GetPrototype(Isolate* isolate);
- // Return the prototype, or the method holder for a value-like object.
- Object* GetDelegate(Isolate* isolate);
-
// Returns the permanent hash code associated with this object depending on
// the actual object type. Might return a failure in case no hash was
// created yet or GC was caused by creation.
@@ -2060,7 +2061,8 @@ class JSObject: public JSReceiver {
int NumberOfLocalProperties(PropertyAttributes filter = NONE);
// Fill in details for properties into storage starting at the specified
// index.
- void GetLocalPropertyNames(FixedArray* storage, int index);
+ void GetLocalPropertyNames(
+ FixedArray* storage, int index, PropertyAttributes filter = NONE);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
@@ -2216,6 +2218,8 @@ class JSObject: public JSReceiver {
static Handle<Object> PreventExtensions(Handle<JSObject> object);
MUST_USE_RESULT MaybeObject* PreventExtensions();
+ // Copy object
+ MUST_USE_RESULT MaybeObject* DeepCopy(Isolate* isolate);
// Dispatched behavior.
void JSObjectShortPrint(StringStream* accumulator);
@@ -3258,7 +3262,10 @@ class Dictionary: public HashTable<Shape, Key> {
PropertyAttributes filter,
SortMode sort_mode);
// Fill in details for properties into storage.
- void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
+ void CopyKeysTo(FixedArray* storage,
+ int index,
+ PropertyAttributes filter,
+ SortMode sort_mode);
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
@@ -4347,6 +4354,11 @@ class Code: public HeapObject {
NONEXISTENT
};
+ enum StubHolder {
+ OWN_STUB,
+ PROTOTYPE_STUB
+ };
+
enum {
NUMBER_OF_KINDS = LAST_IC_KIND + 1
};
@@ -4542,6 +4554,8 @@ class Code: public HeapObject {
class ExtraICStateKeyedAccessStoreMode:
public BitField<KeyedAccessStoreMode, 1, 4> {}; // NOLINT
+ class ExtraICStateStubHolder: public BitField<StubHolder, 0, 1> {};
+
static inline StrictModeFlag GetStrictMode(ExtraICState extra_ic_state) {
return ExtraICStateStrictMode::decode(extra_ic_state);
}
@@ -4558,6 +4572,10 @@ class Code: public HeapObject {
ExtraICStateStrictMode::encode(strict_mode);
}
+ static inline ExtraICState ComputeExtraICState(StubHolder stub_holder) {
+ return ExtraICStateStubHolder::encode(stub_holder);
+ }
+
// Flags operations.
static inline Flags ComputeFlags(
Kind kind,
@@ -5943,6 +5961,9 @@ class SharedFunctionInfo: public HeapObject {
// Indicates that code for this function cannot be cached.
DECL_BOOLEAN_ACCESSORS(dont_cache)
+ // Indicates that this function is a generator.
+ DECL_BOOLEAN_ACCESSORS(is_generator)
+
// Indicates whether or not the code in the shared function support
// deoptimization.
inline bool has_deoptimization_support();
@@ -6169,6 +6190,7 @@ class SharedFunctionInfo: public HeapObject {
kDontOptimize,
kDontInline,
kDontCache,
+ kIsGenerator,
kCompilerHintsCount // Pseudo entry
};
@@ -7401,6 +7423,9 @@ class Name: public HeapObject {
// ES6 symbols.
class Symbol: public Name {
public:
+ // [name]: the print name of a symbol, or undefined if none.
+ DECL_ACCESSORS(name, Object)
+
// Casting.
static inline Symbol* cast(Object* obj);
@@ -7409,7 +7434,11 @@ class Symbol: public Name {
DECLARE_VERIFIER(Symbol)
// Layout description.
- static const int kSize = Name::kSize;
+ static const int kNameOffset = Name::kSize;
+ static const int kSize = kNameOffset + kPointerSize;
+
+ typedef FixedBodyDescriptor<kNameOffset, kNameOffset + kPointerSize, kSize>
+ BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
@@ -7754,8 +7783,8 @@ class SeqString: public String {
// Truncate the string in-place if possible and return the result.
// In case of new_length == 0, the empty string is returned without
// truncating the original string.
- MUST_USE_RESULT String* Truncate(int new_length);
-
+ MUST_USE_RESULT static Handle<String> Truncate(Handle<SeqString> string,
+ int new_length);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
};
@@ -8464,6 +8493,30 @@ class JSWeakMap: public JSObject {
};
+class JSArrayBuffer: public JSObject {
+ public:
+ // [backing_store]: backing memory for thsi array
+ DECL_ACCESSORS(backing_store, void)
+
+ // [byte_length]: length in bytes
+ DECL_ACCESSORS(byte_length, Object)
+
+ // Casting.
+ static inline JSArrayBuffer* cast(Object* obj);
+
+ // Dispatched behavior.
+ DECLARE_PRINTER(JSArrayBuffer)
+ DECLARE_VERIFIER(JSArrayBuffer)
+
+ static const int kBackingStoreOffset = JSObject::kHeaderSize;
+ static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize;
+ static const int kSize = kByteLengthOffset + kPointerSize;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer);
+};
+
+
// Foreign describes objects pointing from JavaScript to C structures.
// Since they cannot contain references to JS HeapObjects they can be
// placed in old_data_space.
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index cdc0adb56..d1228d2f7 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -486,10 +486,12 @@ class Parser::BlockState BASE_EMBEDDED {
Parser::FunctionState::FunctionState(Parser* parser,
Scope* scope,
+ bool is_generator,
Isolate* isolate)
: next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
next_handler_index_(0),
expected_property_count_(0),
+ is_generator_(is_generator),
only_simple_this_property_assignments_(false),
this_property_assignments_(isolate->factory()->empty_fixed_array()),
parser_(parser),
@@ -642,7 +644,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
}
ParsingModeScope parsing_mode(this, mode);
- FunctionState function_state(this, scope, isolate()); // Enters 'scope'.
+ bool is_generator = false;
+ // Enters 'scope'.
+ FunctionState function_state(this, scope, is_generator, isolate());
+
top_scope_->SetLanguageMode(info->language_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
@@ -680,7 +685,8 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::ANONYMOUS_EXPRESSION,
FunctionLiteral::kGlobalOrEval,
- FunctionLiteral::kNotParenthesized);
+ FunctionLiteral::kNotParenthesized,
+ FunctionLiteral::kNotGenerator);
result->set_ast_properties(factory()->visitor()->ast_properties());
} else if (stack_overflow_) {
isolate()->StackOverflow();
@@ -754,7 +760,8 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source,
scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
zone());
}
- FunctionState function_state(this, scope, isolate());
+ bool is_generator = false; // Top scope is not a generator.
+ FunctionState function_state(this, scope, is_generator, isolate());
ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
ASSERT(scope->language_mode() != EXTENDED_MODE ||
info()->is_extended_mode());
@@ -768,6 +775,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source,
bool ok = true;
result = ParseFunctionLiteral(name,
false, // Strict mode name already checked.
+ shared_info->is_generator(),
RelocInfo::kNoPosition,
type,
&ok);
@@ -1132,6 +1140,7 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
// ModuleDeclaration
// ImportDeclaration
// ExportDeclaration
+ // GeneratorDeclaration
switch (peek()) {
case Token::FUNCTION:
@@ -1430,6 +1439,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
// 'export' Identifier (',' Identifier)* ';'
// 'export' VariableDeclaration
// 'export' FunctionDeclaration
+ // 'export' GeneratorDeclaration
// 'export' ModuleDeclaration
//
// TODO(ES6): implement structuring ExportSpecifiers
@@ -1509,6 +1519,7 @@ Statement* Parser::ParseBlockElement(ZoneStringList* labels,
// BlockElement (aka SourceElement):
// LetDeclaration
// ConstDeclaration
+ // GeneratorDeclaration
switch (peek()) {
case Token::FUNCTION:
@@ -1628,6 +1639,10 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// FunctionDeclaration
// Common language extension is to allow function declaration in place
// of any statement. This language extension is disabled in strict mode.
+ //
+ // In Harmony mode, this case also handles the extension:
+ // Statement:
+ // GeneratorDeclaration
if (!top_scope_->is_classic_mode()) {
ReportMessageAt(scanner().peek_location(), "strict_function",
Vector<const char*>::empty());
@@ -1890,13 +1905,18 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
+ // GeneratorDeclaration ::
+ // 'function' '*' Identifier '(' FormalParameterListopt ')'
+ // '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK);
int function_token_position = scanner().location().beg_pos;
+ bool is_generator = FLAG_harmony_generators && Check(Token::MUL);
bool is_strict_reserved = false;
Handle<String> name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
FunctionLiteral* fun = ParseFunctionLiteral(name,
is_strict_reserved,
+ is_generator,
function_token_position,
FunctionLiteral::DECLARATION,
CHECK_OK);
@@ -3004,8 +3024,13 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
// AssignmentExpression ::
// ConditionalExpression
+ // YieldExpression
// LeftHandSideExpression AssignmentOperator AssignmentExpression
+ if (peek() == Token::YIELD && is_generator()) {
+ return ParseYieldExpression(ok);
+ }
+
if (fni_ != NULL) fni_->Enter();
Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
@@ -3074,6 +3099,17 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
}
+Expression* Parser::ParseYieldExpression(bool* ok) {
+ // YieldExpression ::
+ // 'yield' '*'? AssignmentExpression
+ int position = scanner().peek_location().beg_pos;
+ Expect(Token::YIELD, CHECK_OK);
+ bool is_yield_star = Check(Token::MUL);
+ Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
+ return factory()->NewYield(expression, is_yield_star, position);
+}
+
+
// Precedence = 3
Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
// ConditionalExpression ::
@@ -3450,6 +3486,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
if (peek() == Token::FUNCTION) {
Expect(Token::FUNCTION, CHECK_OK);
int function_token_position = scanner().location().beg_pos;
+ bool is_generator = FLAG_harmony_generators && Check(Token::MUL);
Handle<String> name;
bool is_strict_reserved_name = false;
if (peek_any_identifier()) {
@@ -3461,6 +3498,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
: FunctionLiteral::NAMED_EXPRESSION;
result = ParseFunctionLiteral(name,
is_strict_reserved_name,
+ is_generator,
function_token_position,
type,
CHECK_OK);
@@ -3544,6 +3582,7 @@ void Parser::ReportUnexpectedToken(Token::Value token) {
case Token::FUTURE_RESERVED_WORD:
return ReportMessage("unexpected_reserved",
Vector<const char*>::empty());
+ case Token::YIELD:
case Token::FUTURE_STRICT_RESERVED_WORD:
return ReportMessage(top_scope_->is_classic_mode() ?
"unexpected_token_identifier" :
@@ -3604,6 +3643,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
break;
case Token::IDENTIFIER:
+ case Token::YIELD:
case Token::FUTURE_STRICT_RESERVED_WORD: {
Handle<String> name = ParseIdentifier(CHECK_OK);
if (fni_ != NULL) fni_->PushVariableName(name);
@@ -4009,6 +4049,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
FunctionLiteral* value =
ParseFunctionLiteral(name,
false, // reserved words are allowed here
+ false, // not a generator
RelocInfo::kNoPosition,
FunctionLiteral::ANONYMOUS_EXPRESSION,
CHECK_OK);
@@ -4310,6 +4351,7 @@ class SingletonLogger : public ParserRecorder {
FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
bool name_is_strict_reserved,
+ bool is_generator,
int function_token_position,
FunctionLiteral::Type type,
bool* ok) {
@@ -4344,9 +4386,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
? FunctionLiteral::kIsParenthesized
: FunctionLiteral::kNotParenthesized;
+ FunctionLiteral::IsGeneratorFlag generator = is_generator
+ ? FunctionLiteral::kIsGenerator
+ : FunctionLiteral::kNotGenerator;
AstProperties ast_properties;
// Parse function body.
- { FunctionState function_state(this, scope, isolate());
+ { FunctionState function_state(this, scope, is_generator, isolate());
top_scope_->SetScopeName(function_name);
// FormalParameterList ::
@@ -4584,7 +4629,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
duplicate_parameters,
type,
FunctionLiteral::kIsFunction,
- parenthesized);
+ parenthesized,
+ generator);
function_literal->set_function_token_position(function_token_position);
function_literal->set_ast_properties(&ast_properties);
@@ -4606,10 +4652,12 @@ preparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
stack_limit,
do_allow_lazy,
allow_natives_syntax_,
- allow_modules_);
+ allow_modules_,
+ FLAG_harmony_generators);
}
preparser::PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
+ is_generator(),
logger);
return result;
}
@@ -4672,7 +4720,8 @@ bool Parser::peek_any_identifier() {
Token::Value next = peek();
return next == Token::IDENTIFIER ||
next == Token::FUTURE_RESERVED_WORD ||
- next == Token::FUTURE_STRICT_RESERVED_WORD;
+ next == Token::FUTURE_STRICT_RESERVED_WORD ||
+ next == Token::YIELD;
}
@@ -4744,13 +4793,17 @@ Literal* Parser::GetLiteralTheHole() {
// Parses an identifier that is valid for the current scope, in particular it
// fails on strict mode future reserved keywords in a strict scope.
Handle<String> Parser::ParseIdentifier(bool* ok) {
- if (!top_scope_->is_classic_mode()) {
- Expect(Token::IDENTIFIER, ok);
- } else if (!Check(Token::IDENTIFIER)) {
- Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
+ Token::Value next = Next();
+ if (next == Token::IDENTIFIER ||
+ (top_scope_->is_classic_mode() &&
+ (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+ (next == Token::YIELD && !is_generator())))) {
+ return GetSymbol(ok);
+ } else {
+ ReportUnexpectedToken(next);
+ *ok = false;
+ return Handle<String>();
}
- if (!*ok) return Handle<String>();
- return GetSymbol(ok);
}
@@ -4758,12 +4811,17 @@ Handle<String> Parser::ParseIdentifier(bool* ok) {
// whether it is strict mode future reserved.
Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
bool* is_strict_reserved, bool* ok) {
- *is_strict_reserved = false;
- if (!Check(Token::IDENTIFIER)) {
- Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
+ Token::Value next = Next();
+ if (next == Token::IDENTIFIER) {
+ *is_strict_reserved = false;
+ } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+ (next == Token::YIELD && !is_generator())) {
*is_strict_reserved = true;
+ } else {
+ ReportUnexpectedToken(next);
+ *ok = false;
+ return Handle<String>();
}
- if (!*ok) return Handle<String>();
return GetSymbol(ok);
}
@@ -5875,6 +5933,9 @@ ScriptDataImpl* ParserApi::PreParse(Utf16CharacterStream* source,
if (FLAG_lazy && (extension == NULL)) {
flags |= kAllowLazy;
}
+ if (FLAG_harmony_generators) {
+ flags |= kAllowGenerators;
+ }
CompleteParserRecorder recorder;
return DoPreParse(source, flags, &recorder);
}
diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h
index 6dcf7f129..fc4aba2b9 100644
--- a/deps/v8/src/parser.h
+++ b/deps/v8/src/parser.h
@@ -474,6 +474,7 @@ class Parser {
public:
FunctionState(Parser* parser,
Scope* scope,
+ bool is_generator,
Isolate* isolate);
~FunctionState();
@@ -504,6 +505,8 @@ class Parser {
void AddProperty() { expected_property_count_++; }
int expected_property_count() { return expected_property_count_; }
+ bool is_generator() const { return is_generator_; }
+
AstNodeFactory<AstConstructionVisitor>* factory() { return &factory_; }
private:
@@ -518,6 +521,9 @@ class Parser {
// Properties count estimation.
int expected_property_count_;
+ // Indicates that this function is a generator.
+ bool is_generator_;
+
// Keeps track of assignments to properties of this. Used for
// optimizing constructors.
bool only_simple_this_property_assignments_;
@@ -631,6 +637,7 @@ class Parser {
Expression* ParseExpression(bool accept_IN, bool* ok);
Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
+ Expression* ParseYieldExpression(bool* ok);
Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
Expression* ParseUnaryExpression(bool* ok);
@@ -674,6 +681,7 @@ class Parser {
ZoneList<Expression*>* ParseArguments(bool* ok);
FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
bool name_is_reserved,
+ bool is_generator,
int function_token_position,
FunctionLiteral::Type type,
bool* ok);
@@ -703,6 +711,8 @@ class Parser {
return scanner().Next();
}
+ bool is_generator() const { return current_function_state_->is_generator(); }
+
bool peek_any_identifier();
INLINE(void Consume(Token::Value token));
diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc
index d21f160b4..1f9cde151 100644
--- a/deps/v8/src/platform-linux.cc
+++ b/deps/v8/src/platform-linux.cc
@@ -111,8 +111,10 @@ static bool CPUInfoContainsString(const char * search_string) {
FILE* f = NULL;
const char* what = search_string;
- if (NULL == (f = fopen(file_name, "r")))
+ if (NULL == (f = fopen(file_name, "r"))) {
+ OS::PrintError("Failed to open /proc/cpuinfo\n");
return false;
+ }
int k;
while (EOF != (k = fgetc(f))) {
diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc
index 69d39112a..0016d59d3 100644
--- a/deps/v8/src/platform-posix.cc
+++ b/deps/v8/src/platform-posix.cc
@@ -109,26 +109,11 @@ void* OS::GetRandomMmapAddr() {
raw_addr &= V8_UINT64_C(0x3ffffffff000);
#else
uint32_t raw_addr = V8::RandomPrivate(isolate);
-
- raw_addr &= 0x3ffff000;
-
-# ifdef __sun
- // For our Solaris/illumos mmap hint, we pick a random address in the bottom
- // half of the top half of the address space (that is, the third quarter).
- // Because we do not MAP_FIXED, this will be treated only as a hint -- the
- // system will not fail to mmap() because something else happens to already
- // be mapped at our random address. We deliberately set the hint high enough
- // to get well above the system's break (that is, the heap); Solaris and
- // illumos will try the hint and if that fails allocate as if there were
- // no hint at all. The high hint prevents the break from getting hemmed in
- // at low values, ceding half of the address space to the system heap.
- raw_addr += 0x80000000;
-# else
// The range 0x20000000 - 0x60000000 is relatively unpopulated across a
// variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
// 10.6 and 10.7.
+ raw_addr &= 0x3ffff000;
raw_addr += 0x20000000;
-# endif
#endif
return reinterpret_cast<void*>(raw_addr);
}
diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h
index 56ac61dc7..f2a228c92 100644
--- a/deps/v8/src/platform.h
+++ b/deps/v8/src/platform.h
@@ -348,7 +348,7 @@ class OS {
static void MemCopy(void* dest, const void* src, size_t size) {
memcpy(dest, src, size);
}
- static const int kMinComplexMemCopy = 256;
+ static const int kMinComplexMemCopy = 16 * kPointerSize;
#endif // V8_TARGET_ARCH_IA32
static int GetCurrentProcessId();
diff --git a/deps/v8/src/preparser.cc b/deps/v8/src/preparser.cc
index c461d8a4b..c61a08db9 100644
--- a/deps/v8/src/preparser.cc
+++ b/deps/v8/src/preparser.cc
@@ -53,12 +53,13 @@ int isfinite(double value);
namespace preparser {
PreParser::PreParseResult PreParser::PreParseLazyFunction(
- i::LanguageMode mode, i::ParserRecorder* log) {
+ i::LanguageMode mode, bool is_generator, i::ParserRecorder* log) {
log_ = log;
// Lazy functions always have trivial outer scopes (no with/catch scopes).
Scope top_scope(&scope_, kTopLevelScope);
set_language_mode(mode);
Scope function_scope(&scope_, kFunctionScope);
+ function_scope.set_is_generator(is_generator);
ASSERT_EQ(i::Token::LBRACE, scanner_->current_token());
bool ok = true;
int start_position = scanner_->peek_location().beg_pos;
@@ -154,6 +155,7 @@ PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
// SourceElement:
// LetDeclaration
// ConstDeclaration
+ // GeneratorDeclaration
switch (peek()) {
case i::Token::FUNCTION:
@@ -294,19 +296,23 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
+ // GeneratorDeclaration ::
+ // 'function' '*' Identifier '(' FormalParameterListopt ')'
+ // '{' FunctionBody '}'
Expect(i::Token::FUNCTION, CHECK_OK);
+ bool is_generator = allow_generators_ && Check(i::Token::MUL);
Identifier identifier = ParseIdentifier(CHECK_OK);
i::Scanner::Location location = scanner_->location();
- Expression function_value = ParseFunctionLiteral(CHECK_OK);
+ Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
if (function_value.IsStrictFunction() &&
!identifier.IsValidStrictVariable()) {
// Strict mode violation, using either reserved word or eval/arguments
// as name of strict function.
const char* type = "strict_function_name";
- if (identifier.IsFutureStrictReserved()) {
+ if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
type = "strict_reserved_word";
}
ReportMessageAt(location, type, NULL);
@@ -475,7 +481,9 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
Expression expr = ParseExpression(true, CHECK_OK);
if (expr.IsRawIdentifier()) {
ASSERT(!expr.AsIdentifier().IsFutureReserved());
- ASSERT(is_classic_mode() || !expr.AsIdentifier().IsFutureStrictReserved());
+ ASSERT(is_classic_mode() ||
+ (!expr.AsIdentifier().IsFutureStrictReserved() &&
+ !expr.AsIdentifier().IsYield()));
if (peek() == i::Token::COLON) {
Consume(i::Token::COLON);
return ParseStatement(ok);
@@ -810,8 +818,13 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
bool* ok) {
// AssignmentExpression ::
// ConditionalExpression
+ // YieldExpression
// LeftHandSideExpression AssignmentOperator AssignmentExpression
+ if (scope_->is_generator() && peek() == i::Token::YIELD) {
+ return ParseYieldExpression(ok);
+ }
+
i::Scanner::Location before = scanner_->peek_location();
Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
@@ -842,6 +855,19 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
// Precedence = 3
+PreParser::Expression PreParser::ParseYieldExpression(bool* ok) {
+ // YieldExpression ::
+ // 'yield' '*'? AssignmentExpression
+ Consume(i::Token::YIELD);
+ Check(i::Token::MUL);
+
+ ParseAssignmentExpression(false, CHECK_OK);
+
+ return Expression::Default();
+}
+
+
+// Precedence = 3
PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
bool* ok) {
// ConditionalExpression ::
@@ -1034,11 +1060,13 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
Expression result = Expression::Default();
if (peek() == i::Token::FUNCTION) {
Consume(i::Token::FUNCTION);
+
+ bool is_generator = allow_generators_ && Check(i::Token::MUL);
Identifier identifier = Identifier::Default();
if (peek_any_identifier()) {
identifier = ParseIdentifier(CHECK_OK);
}
- result = ParseFunctionLiteral(CHECK_OK);
+ result = ParseFunctionLiteral(is_generator, CHECK_OK);
if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
StrictModeIdentifierViolation(scanner_->location(),
"strict_function_name",
@@ -1112,6 +1140,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
case i::Token::FUTURE_RESERVED_WORD:
case i::Token::FUTURE_STRICT_RESERVED_WORD:
+ case i::Token::YIELD:
case i::Token::IDENTIFIER: {
Identifier id = ParseIdentifier(CHECK_OK);
result = Expression::FromIdentifier(id);
@@ -1257,7 +1286,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
}
PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
- ParseFunctionLiteral(CHECK_OK);
+ ParseFunctionLiteral(false, CHECK_OK);
if (peek() != i::Token::RBRACE) {
Expect(i::Token::COMMA, CHECK_OK);
}
@@ -1344,7 +1373,8 @@ PreParser::Arguments PreParser::ParseArguments(bool* ok) {
}
-PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
+PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
+ bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
@@ -1352,6 +1382,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
ScopeType outer_scope_type = scope_->type();
bool inside_with = scope_->IsInsideWith();
Scope function_scope(&scope_, kFunctionScope);
+ function_scope.set_is_generator(is_generator);
// FormalParameterList ::
// '(' (Identifier)*[','] ')'
Expect(i::Token::LPAREN, CHECK_OK);
@@ -1497,6 +1528,8 @@ PreParser::Identifier PreParser::GetIdentifierSymbol() {
} else if (scanner_->current_token() ==
i::Token::FUTURE_STRICT_RESERVED_WORD) {
return Identifier::FutureStrictReserved();
+ } else if (scanner_->current_token() == i::Token::YIELD) {
+ return Identifier::Yield();
}
if (scanner_->is_literal_ascii()) {
// Detect strict-mode poison words.
@@ -1523,6 +1556,14 @@ PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
*ok = false;
return GetIdentifierSymbol();
}
+ case i::Token::YIELD:
+ if (scope_->is_generator()) {
+ // 'yield' in a generator is only valid as part of a YieldExpression.
+ ReportMessageAt(scanner_->location(), "unexpected_token", "yield");
+ *ok = false;
+ return Identifier::Yield();
+ }
+ // FALLTHROUGH
case i::Token::FUTURE_STRICT_RESERVED_WORD:
if (!is_classic_mode()) {
i::Scanner::Location location = scanner_->location();
@@ -1580,7 +1621,7 @@ void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
const char* type = eval_args_type;
if (identifier.IsFutureReserved()) {
type = "reserved_word";
- } else if (identifier.IsFutureStrictReserved()) {
+ } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
type = "strict_reserved_word";
}
if (!is_classic_mode()) {
@@ -1634,7 +1675,8 @@ bool PreParser::peek_any_identifier() {
i::Token::Value next = peek();
return next == i::Token::IDENTIFIER ||
next == i::Token::FUTURE_RESERVED_WORD ||
- next == i::Token::FUTURE_STRICT_RESERVED_WORD;
+ next == i::Token::FUTURE_STRICT_RESERVED_WORD ||
+ next == i::Token::YIELD;
}
diff --git a/deps/v8/src/preparser.h b/deps/v8/src/preparser.h
index ad52d74bb..ce9aa7546 100644
--- a/deps/v8/src/preparser.h
+++ b/deps/v8/src/preparser.h
@@ -104,6 +104,11 @@ class DuplicateFinder {
};
+#ifdef WIN32
+#undef Yield
+#endif
+
+
class PreParser {
public:
enum PreParseResult {
@@ -117,7 +122,8 @@ class PreParser {
uintptr_t stack_limit,
bool allow_lazy,
bool allow_natives_syntax,
- bool allow_modules)
+ bool allow_modules,
+ bool allow_generators)
: scanner_(scanner),
log_(log),
scope_(NULL),
@@ -128,6 +134,7 @@ class PreParser {
allow_lazy_(allow_lazy),
allow_modules_(allow_modules),
allow_natives_syntax_(allow_natives_syntax),
+ allow_generators_(allow_generators),
parenthesized_function_(false),
harmony_scoping_(scanner->HarmonyScoping()) { }
@@ -144,19 +151,22 @@ class PreParser {
bool allow_lazy = (flags & i::kAllowLazy) != 0;
bool allow_natives_syntax = (flags & i::kAllowNativesSyntax) != 0;
bool allow_modules = (flags & i::kAllowModules) != 0;
+ bool allow_generators = (flags & i::kAllowGenerators) != 0;
return PreParser(scanner, log, stack_limit, allow_lazy,
- allow_natives_syntax, allow_modules).PreParse();
+ allow_natives_syntax, allow_modules,
+ allow_generators).PreParse();
}
// Parses a single function literal, from the opening parentheses before
// parameters to the closing brace after the body.
// Returns a FunctionEntry describing the body of the function in enough
// detail that it can be lazily compiled.
- // The scanner is expected to have matched the "function" keyword and
- // parameters, and have consumed the initial '{'.
+ // The scanner is expected to have matched the "function" or "function*"
+ // keyword and parameters, and have consumed the initial '{'.
// At return, unless an error occurred, the scanner is positioned before the
// the final '}'.
PreParseResult PreParseLazyFunction(i::LanguageMode mode,
+ bool is_generator,
i::ParserRecorder* log);
private:
@@ -240,9 +250,13 @@ class PreParser {
static Identifier FutureStrictReserved() {
return Identifier(kFutureStrictReservedIdentifier);
}
+ static Identifier Yield() {
+ return Identifier(kYieldIdentifier);
+ }
bool IsEval() { return type_ == kEvalIdentifier; }
bool IsArguments() { return type_ == kArgumentsIdentifier; }
bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
+ bool IsYield() { return type_ == kYieldIdentifier; }
bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
bool IsFutureStrictReserved() {
return type_ == kFutureStrictReservedIdentifier;
@@ -254,6 +268,7 @@ class PreParser {
kUnknownIdentifier,
kFutureReservedIdentifier,
kFutureStrictReservedIdentifier,
+ kYieldIdentifier,
kEvalIdentifier,
kArgumentsIdentifier
};
@@ -347,7 +362,7 @@ class PreParser {
// Identifiers and string literals can be parenthesized.
// They no longer work as labels or directive prologues,
// but are still recognized in other contexts.
- return Expression(code_ | kParentesizedExpressionFlag);
+ return Expression(code_ | kParenthesizedExpressionFlag);
}
// For other types of expressions, it's not important to remember
// the parentheses.
@@ -373,7 +388,8 @@ class PreParser {
kUseStrictString = kStringLiteralFlag | 8,
kStringLiteralMask = kUseStrictString,
- kParentesizedExpressionFlag = 4, // Only if identifier or string literal.
+ // Only if identifier or string literal.
+ kParenthesizedExpressionFlag = 4,
// Below here applies if neither identifier nor string literal.
kThisExpression = 4,
@@ -451,7 +467,8 @@ class PreParser {
expected_properties_(0),
with_nesting_count_(0),
language_mode_(
- (prev_ != NULL) ? prev_->language_mode() : i::CLASSIC_MODE) {
+ (prev_ != NULL) ? prev_->language_mode() : i::CLASSIC_MODE),
+ is_generator_(false) {
*variable = this;
}
~Scope() { *variable_ = prev_; }
@@ -461,6 +478,8 @@ class PreParser {
int expected_properties() { return expected_properties_; }
int materialized_literal_count() { return materialized_literal_count_; }
bool IsInsideWith() { return with_nesting_count_ != 0; }
+ bool is_generator() { return is_generator_; }
+ void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
bool is_classic_mode() {
return language_mode_ == i::CLASSIC_MODE;
}
@@ -492,6 +511,7 @@ class PreParser {
int expected_properties_;
int with_nesting_count_;
i::LanguageMode language_mode_;
+ bool is_generator_;
};
// Preparse the program. Only called in PreParseProgram after creating
@@ -557,6 +577,7 @@ class PreParser {
Expression ParseExpression(bool accept_IN, bool* ok);
Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
+ Expression ParseYieldExpression(bool* ok);
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
Expression ParseUnaryExpression(bool* ok);
@@ -572,7 +593,7 @@ class PreParser {
Expression ParseV8Intrinsic(bool* ok);
Arguments ParseArguments(bool* ok);
- Expression ParseFunctionLiteral(bool* ok);
+ Expression ParseFunctionLiteral(bool is_generator, bool* ok);
void ParseLazyFunctionLiteralBody(bool* ok);
Identifier ParseIdentifier(bool* ok);
@@ -664,6 +685,7 @@ class PreParser {
bool allow_lazy_;
bool allow_modules_;
bool allow_natives_syntax_;
+ bool allow_generators_;
bool parenthesized_function_;
bool harmony_scoping_;
};
diff --git a/deps/v8/src/prettyprinter.cc b/deps/v8/src/prettyprinter.cc
index df6183a36..50a71ced3 100644
--- a/deps/v8/src/prettyprinter.cc
+++ b/deps/v8/src/prettyprinter.cc
@@ -353,6 +353,12 @@ void PrettyPrinter::VisitAssignment(Assignment* node) {
}
+void PrettyPrinter::VisitYield(Yield* node) {
+ Print("yield ");
+ Visit(node->expression());
+}
+
+
void PrettyPrinter::VisitThrow(Throw* node) {
Print("throw ");
Visit(node->exception());
@@ -1059,6 +1065,11 @@ void AstPrinter::VisitAssignment(Assignment* node) {
}
+void AstPrinter::VisitYield(Yield* node) {
+ PrintIndentedVisit("YIELD", node->expression());
+}
+
+
void AstPrinter::VisitThrow(Throw* node) {
PrintIndentedVisit("THROW", node->exception());
}
diff --git a/deps/v8/src/property.h b/deps/v8/src/property.h
index 546967ac4..bbba8aea6 100644
--- a/deps/v8/src/property.h
+++ b/deps/v8/src/property.h
@@ -362,12 +362,16 @@ class LookupResult BASE_EMBEDDED {
return NULL;
}
- Map* GetTransitionTarget() {
+ Map* GetTransitionTarget(Map* map) {
ASSERT(IsTransition());
- TransitionArray* transitions = holder()->map()->transitions();
+ TransitionArray* transitions = map->transitions();
return transitions->GetTarget(number_);
}
+ Map* GetTransitionTarget() {
+ return GetTransitionTarget(holder()->map());
+ }
+
PropertyDetails GetTransitionDetails(Map* map) {
ASSERT(IsTransition());
TransitionArray* transitions = map->transitions();
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index e220d6bed..78efc8dbe 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -26,6 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
+#include <limits>
#include "v8.h"
@@ -138,148 +139,6 @@ namespace internal {
static_cast<LanguageMode>(args.smi_at(index));
-MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
- JSObject* boilerplate) {
- StackLimitCheck check(isolate);
- if (check.HasOverflowed()) return isolate->StackOverflow();
-
- Heap* heap = isolate->heap();
- Object* result;
- { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- JSObject* copy = JSObject::cast(result);
-
- // Deep copy local properties.
- if (copy->HasFastProperties()) {
- FixedArray* properties = copy->properties();
- for (int i = 0; i < properties->length(); i++) {
- Object* value = properties->get(i);
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- properties->set(i, result);
- }
- }
- int nof = copy->map()->inobject_properties();
- for (int i = 0; i < nof; i++) {
- Object* value = copy->InObjectPropertyAt(i);
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- copy->InObjectPropertyAtPut(i, result);
- }
- }
- } else {
- { MaybeObject* maybe_result =
- heap->AllocateFixedArray(copy->NumberOfLocalProperties());
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- FixedArray* names = FixedArray::cast(result);
- copy->GetLocalPropertyNames(names, 0);
- for (int i = 0; i < names->length(); i++) {
- ASSERT(names->get(i)->IsString());
- String* key_string = String::cast(names->get(i));
- PropertyAttributes attributes =
- copy->GetLocalPropertyAttribute(key_string);
- // Only deep copy fields from the object literal expression.
- // In particular, don't try to copy the length attribute of
- // an array.
- if (attributes != NONE) continue;
- Object* value =
- copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- { MaybeObject* maybe_result =
- // Creating object copy for literals. No strict mode needed.
- copy->SetProperty(key_string, result, NONE, kNonStrictMode);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- }
- }
- }
-
- // Deep copy local elements.
- // Pixel elements cannot be created using an object literal.
- ASSERT(!copy->HasExternalArrayElements());
- switch (copy->GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
- case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS: {
- FixedArray* elements = FixedArray::cast(copy->elements());
- if (elements->map() == heap->fixed_cow_array_map()) {
- isolate->counters()->cow_arrays_created_runtime()->Increment();
-#ifdef DEBUG
- for (int i = 0; i < elements->length(); i++) {
- ASSERT(!elements->get(i)->IsJSObject());
- }
-#endif
- } else {
- for (int i = 0; i < elements->length(); i++) {
- Object* value = elements->get(i);
- ASSERT(value->IsSmi() ||
- value->IsTheHole() ||
- (IsFastObjectElementsKind(copy->GetElementsKind())));
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
- js_object);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- elements->set(i, result);
- }
- }
- }
- break;
- }
- case DICTIONARY_ELEMENTS: {
- SeededNumberDictionary* element_dictionary = copy->element_dictionary();
- int capacity = element_dictionary->Capacity();
- for (int i = 0; i < capacity; i++) {
- Object* k = element_dictionary->KeyAt(i);
- if (element_dictionary->IsKey(k)) {
- Object* value = element_dictionary->ValueAt(i);
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
- js_object);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- element_dictionary->ValueAtPut(i, result);
- }
- }
- }
- break;
- }
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
- break;
- case EXTERNAL_PIXEL_ELEMENTS:
- case EXTERNAL_BYTE_ELEMENTS:
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- case EXTERNAL_SHORT_ELEMENTS:
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- case EXTERNAL_INT_ELEMENTS:
- case EXTERNAL_UNSIGNED_INT_ELEMENTS:
- case EXTERNAL_FLOAT_ELEMENTS:
- case EXTERNAL_DOUBLE_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
- // No contained objects, nothing to do.
- break;
- }
- return copy;
-}
-
-
static Handle<Map> ComputeObjectLiteralMap(
Handle<Context> context,
Handle<FixedArray> constant_properties,
@@ -598,7 +457,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
// Update the functions literal and return the boilerplate.
literals->set(literals_index, *boilerplate);
}
- return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
+ return JSObject::cast(*boilerplate)->DeepCopy(isolate);
}
@@ -645,7 +504,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
// Update the functions literal and return the boilerplate.
literals->set(literals_index, *boilerplate);
}
- return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
+ return JSObject::cast(*boilerplate)->DeepCopy(isolate);
}
@@ -683,9 +542,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ Handle<Object> name(args[0], isolate);
+ RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
+ Symbol* symbol;
+ MaybeObject* maybe = isolate->heap()->AllocateSymbol();
+ if (!maybe->To(&symbol)) return maybe;
+ if (name->IsString()) symbol->set_name(*name);
+ return symbol;
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
NoHandleAllocation ha(isolate);
- ASSERT(args.length() == 0);
- return isolate->heap()->AllocateSymbol();
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Symbol, symbol, 0);
+ return symbol->name();
}
@@ -764,6 +637,125 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
}
+static size_t ArrayBufferAllocatedLength(Isolate* isolate,
+ JSArrayBuffer* buffer) {
+ NoHandleAllocation hc(isolate);
+ Object* byte_length = buffer->byte_length();
+ if (byte_length->IsSmi()) {
+ return Smi::cast(byte_length)->value();
+ } else {
+ double value = HeapNumber::cast(byte_length)->value();
+ return static_cast<size_t>(value);
+ }
+}
+
+
+static void ArrayBufferWeakCallback(v8::Isolate* external_isolate,
+ Persistent<Value> object,
+ void* data) {
+ Isolate* isolate = reinterpret_cast<Isolate*>(external_isolate);
+ HandleScope scope(isolate);
+ Handle<Object> internal_object = Utils::OpenHandle(*object);
+
+ size_t allocated_length = ArrayBufferAllocatedLength(
+ isolate, JSArrayBuffer::cast(*internal_object));
+ isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
+ -static_cast<intptr_t>(allocated_length));
+ if (data != NULL)
+ free(data);
+ object.Dispose(external_isolate);
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
+ size_t allocated_length;
+ if (byteLength->IsSmi()) {
+ allocated_length = Smi::cast(*byteLength)->value();
+ } else {
+ ASSERT(byteLength->IsHeapNumber());
+ double value = HeapNumber::cast(*byteLength)->value();
+
+ ASSERT(value >= 0);
+
+ if (value > std::numeric_limits<size_t>::max()) {
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
+ }
+
+ allocated_length = static_cast<size_t>(value);
+ }
+
+ void* data;
+ if (allocated_length != 0) {
+ data = malloc(allocated_length);
+
+ if (data == NULL) {
+ return isolate->Throw(*isolate->factory()->
+ NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
+ }
+
+ memset(data, 0, allocated_length);
+ } else {
+ data = NULL;
+ }
+ holder->set_backing_store(data);
+
+ Object* byte_length;
+ {
+ MaybeObject* maybe_byte_length =
+ isolate->heap()->NumberFromDouble(
+ static_cast<double>(allocated_length));
+ if (!maybe_byte_length->ToObject(&byte_length)) return maybe_byte_length;
+ }
+ CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
+ holder->set_byte_length(byte_length);
+
+ v8::Isolate* external_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+ v8::Handle<Object> external_holder(*holder);
+ Persistent<Object> weak_handle = Persistent<Object>::New(
+ external_isolate, external_holder);
+ weak_handle.MakeWeak(external_isolate, data, ArrayBufferWeakCallback);
+ weak_handle.MarkIndependent(external_isolate);
+ isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
+
+ return *holder;
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
+ NoHandleAllocation ha(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
+ return holder->byte_length();
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
+ CONVERT_DOUBLE_ARG_CHECKED(first, 2);
+ size_t start = static_cast<size_t>(first);
+ size_t target_length = ArrayBufferAllocatedLength(isolate, *target);
+
+ if (target_length == 0)
+ return isolate->heap()->undefined_value();
+
+ ASSERT(ArrayBufferAllocatedLength(isolate, *source) - target_length >= start);
+ uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
+ uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
+ CopyBytes(target_data, source_data + start, target_length);
+ return isolate->heap()->undefined_value();
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -4731,11 +4723,13 @@ static int LocalPrototypeChainLength(JSObject* obj) {
// args[0]: object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
HandleScope scope(isolate);
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 2);
if (!args[0]->IsJSObject()) {
return isolate->heap()->undefined_value();
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
+ CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
+ PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
@@ -4768,7 +4762,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
return *isolate->factory()->NewJSArray(0);
}
int n;
- n = jsproto->NumberOfLocalProperties();
+ n = jsproto->NumberOfLocalProperties(filter);
local_property_count[i] = n;
total_property_count += n;
if (i < length - 1) {
@@ -4785,7 +4779,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
int proto_with_hidden_properties = 0;
int next_copy_index = 0;
for (int i = 0; i < length; i++) {
- jsproto->GetLocalPropertyNames(*names, next_copy_index);
+ jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
next_copy_index += local_property_count[i];
if (jsproto->HasHiddenProperties()) {
proto_with_hidden_properties++;
@@ -4795,7 +4789,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
}
}
- // Filter out name of hidden propeties object.
+ // Filter out name of hidden properties object.
if (proto_with_hidden_properties > 0) {
Handle<FixedArray> old_names = names;
names = isolate->factory()->NewFixedArray(
@@ -5035,6 +5029,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
}
ASSERT(heap_obj->IsUndefined());
return isolate->heap()->undefined_string();
+ case SYMBOL_TYPE:
+ return isolate->heap()->symbol_string();
case JS_FUNCTION_TYPE:
case JS_FUNCTION_PROXY_TYPE:
return isolate->heap()->function_string();
@@ -5137,10 +5133,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
- NoHandleAllocation ha(isolate);
- CONVERT_ARG_CHECKED(SeqString, string, 0);
+ HandleScope scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
CONVERT_SMI_ARG_CHECKED(new_length, 1);
- return string->Truncate(new_length);
+ return *SeqString::Truncate(string, new_length);
}
@@ -5171,365 +5167,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
}
-static const unsigned int kQuoteTableLength = 128u;
-
-static const int kJsonQuotesCharactersPerEntry = 8;
-static const char* const JsonQuotes =
- "\\u0000 \\u0001 \\u0002 \\u0003 "
- "\\u0004 \\u0005 \\u0006 \\u0007 "
- "\\b \\t \\n \\u000b "
- "\\f \\r \\u000e \\u000f "
- "\\u0010 \\u0011 \\u0012 \\u0013 "
- "\\u0014 \\u0015 \\u0016 \\u0017 "
- "\\u0018 \\u0019 \\u001a \\u001b "
- "\\u001c \\u001d \\u001e \\u001f "
- " ! \\\" # "
- "$ % & ' "
- "( ) * + "
- ", - . / "
- "0 1 2 3 "
- "4 5 6 7 "
- "8 9 : ; "
- "< = > ? "
- "@ A B C "
- "D E F G "
- "H I J K "
- "L M N O "
- "P Q R S "
- "T U V W "
- "X Y Z [ "
- "\\\\ ] ^ _ "
- "` a b c "
- "d e f g "
- "h i j k "
- "l m n o "
- "p q r s "
- "t u v w "
- "x y z { "
- "| } ~ \177 ";
-
-
-// For a string that is less than 32k characters it should always be
-// possible to allocate it in new space.
-static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
-
-
-// Doing JSON quoting cannot make the string more than this many times larger.
-static const int kJsonQuoteWorstCaseBlowup = 6;
-
-static const int kSpaceForQuotesAndComma = 3;
-static const int kSpaceForBrackets = 2;
-
-// Covers the entire ASCII range (all other characters are unchanged by JSON
-// quoting).
-static const byte JsonQuoteLengths[kQuoteTableLength] = {
- 6, 6, 6, 6, 6, 6, 6, 6,
- 2, 2, 2, 6, 2, 2, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 1, 1, 2, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
-};
-
-
-template <typename StringType>
-MaybeObject* AllocateRawString(Isolate* isolate, int length);
-
-
-template <>
-MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
- return isolate->heap()->AllocateRawTwoByteString(length);
-}
-
-
-template <>
-MaybeObject* AllocateRawString<SeqOneByteString>(Isolate* isolate, int length) {
- return isolate->heap()->AllocateRawOneByteString(length);
-}
-
-
-template <typename Char, typename StringType, bool comma>
-static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
- Vector<const Char> characters) {
- int length = characters.length();
- const Char* read_cursor = characters.start();
- const Char* end = read_cursor + length;
- const int kSpaceForQuotes = 2 + (comma ? 1 :0);
- int quoted_length = kSpaceForQuotes;
- while (read_cursor < end) {
- Char c = *(read_cursor++);
- if (static_cast<unsigned>(c) >= kQuoteTableLength) {
- quoted_length++;
- } else {
- quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
- }
- }
- MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
- quoted_length);
- Object* new_object;
- if (!new_alloc->ToObject(&new_object)) {
- return new_alloc;
- }
- StringType* new_string = StringType::cast(new_object);
-
- Char* write_cursor = reinterpret_cast<Char*>(
- new_string->address() + SeqString::kHeaderSize);
- if (comma) *(write_cursor++) = ',';
- *(write_cursor++) = '"';
-
- read_cursor = characters.start();
- while (read_cursor < end) {
- Char c = *(read_cursor++);
- if (static_cast<unsigned>(c) >= kQuoteTableLength) {
- *(write_cursor++) = c;
- } else {
- int len = JsonQuoteLengths[static_cast<unsigned>(c)];
- const char* replacement = JsonQuotes +
- static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
- for (int i = 0; i < len; i++) {
- *write_cursor++ = *replacement++;
- }
- }
- }
- *(write_cursor++) = '"';
- return new_string;
-}
-
-
-template <typename SinkChar, typename SourceChar>
-static inline SinkChar* WriteQuoteJsonString(
- Isolate* isolate,
- SinkChar* write_cursor,
- Vector<const SourceChar> characters) {
- // SinkChar is only char if SourceChar is guaranteed to be char.
- ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
- const SourceChar* read_cursor = characters.start();
- const SourceChar* end = read_cursor + characters.length();
- *(write_cursor++) = '"';
- while (read_cursor < end) {
- SourceChar c = *(read_cursor++);
- if (static_cast<unsigned>(c) >= kQuoteTableLength) {
- *(write_cursor++) = static_cast<SinkChar>(c);
- } else {
- int len = JsonQuoteLengths[static_cast<unsigned>(c)];
- const char* replacement = JsonQuotes +
- static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
- write_cursor[0] = replacement[0];
- if (len > 1) {
- write_cursor[1] = replacement[1];
- if (len > 2) {
- ASSERT(len == 6);
- write_cursor[2] = replacement[2];
- write_cursor[3] = replacement[3];
- write_cursor[4] = replacement[4];
- write_cursor[5] = replacement[5];
- }
- }
- write_cursor += len;
- }
- }
- *(write_cursor++) = '"';
- return write_cursor;
-}
-
-
-template <typename Char, typename StringType, bool comma>
-static MaybeObject* QuoteJsonString(Isolate* isolate,
- Vector<const Char> characters) {
- int length = characters.length();
- isolate->counters()->quote_json_char_count()->Increment(length);
- int worst_case_length =
- length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
- if (worst_case_length > kMaxGuaranteedNewSpaceString) {
- return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
- }
-
- MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
- worst_case_length);
- Object* new_object;
- if (!new_alloc->ToObject(&new_object)) {
- return new_alloc;
- }
- if (!isolate->heap()->new_space()->Contains(new_object)) {
- // Even if our string is small enough to fit in new space we still have to
- // handle it being allocated in old space as may happen in the third
- // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
- // CEntryStub::GenerateCore.
- return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
- }
- StringType* new_string = StringType::cast(new_object);
- ASSERT(isolate->heap()->new_space()->Contains(new_string));
-
- Char* write_cursor = reinterpret_cast<Char*>(
- new_string->address() + SeqString::kHeaderSize);
- if (comma) *(write_cursor++) = ',';
- write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
- write_cursor,
- characters);
- int final_length = static_cast<int>(
- write_cursor - reinterpret_cast<Char*>(
- new_string->address() + SeqString::kHeaderSize));
- isolate->heap()->new_space()->
- template ShrinkStringAtAllocationBoundary<StringType>(
- new_string, final_length);
- return new_string;
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
- NoHandleAllocation ha(isolate);
- CONVERT_ARG_CHECKED(String, str, 0);
- if (!str->IsFlat()) {
- MaybeObject* try_flatten = str->TryFlatten();
- Object* flat;
- if (!try_flatten->ToObject(&flat)) {
- return try_flatten;
- }
- str = String::cast(flat);
- ASSERT(str->IsFlat());
- }
- String::FlatContent flat = str->GetFlatContent();
- ASSERT(flat.IsFlat());
- if (flat.IsTwoByte()) {
- return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
- flat.ToUC16Vector());
- } else {
- return QuoteJsonString<uint8_t, SeqOneByteString, false>(
- isolate,
- flat.ToOneByteVector());
- }
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
- NoHandleAllocation ha(isolate);
- CONVERT_ARG_CHECKED(String, str, 0);
- if (!str->IsFlat()) {
- MaybeObject* try_flatten = str->TryFlatten();
- Object* flat;
- if (!try_flatten->ToObject(&flat)) {
- return try_flatten;
- }
- str = String::cast(flat);
- ASSERT(str->IsFlat());
- }
- String::FlatContent flat = str->GetFlatContent();
- if (flat.IsTwoByte()) {
- return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
- flat.ToUC16Vector());
- } else {
- return QuoteJsonString<uint8_t, SeqOneByteString, true>(
- isolate,
- flat.ToOneByteVector());
- }
-}
-
-
-template <typename Char, typename StringType>
-static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
- FixedArray* array,
- int worst_case_length) {
- int length = array->length();
-
- MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
- worst_case_length);
- Object* new_object;
- if (!new_alloc->ToObject(&new_object)) {
- return new_alloc;
- }
- if (!isolate->heap()->new_space()->Contains(new_object)) {
- // Even if our string is small enough to fit in new space we still have to
- // handle it being allocated in old space as may happen in the third
- // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
- // CEntryStub::GenerateCore.
- return isolate->heap()->undefined_value();
- }
- AssertNoAllocation no_gc;
- StringType* new_string = StringType::cast(new_object);
- ASSERT(isolate->heap()->new_space()->Contains(new_string));
-
- Char* write_cursor = reinterpret_cast<Char*>(
- new_string->address() + SeqString::kHeaderSize);
- *(write_cursor++) = '[';
- for (int i = 0; i < length; i++) {
- if (i != 0) *(write_cursor++) = ',';
- String* str = String::cast(array->get(i));
- String::FlatContent content = str->GetFlatContent();
- ASSERT(content.IsFlat());
- if (content.IsTwoByte()) {
- write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
- write_cursor,
- content.ToUC16Vector());
- } else {
- write_cursor =
- WriteQuoteJsonString<Char, uint8_t>(isolate,
- write_cursor,
- content.ToOneByteVector());
- }
- }
- *(write_cursor++) = ']';
-
- int final_length = static_cast<int>(
- write_cursor - reinterpret_cast<Char*>(
- new_string->address() + SeqString::kHeaderSize));
- isolate->heap()->new_space()->
- template ShrinkStringAtAllocationBoundary<StringType>(
- new_string, final_length);
- return new_string;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
- NoHandleAllocation ha(isolate);
+ HandleScope scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSArray, array, 0);
-
- if (!array->HasFastObjectElements()) {
- return isolate->heap()->undefined_value();
- }
- FixedArray* elements = FixedArray::cast(array->elements());
- int n = elements->length();
- bool ascii = true;
- int total_length = 0;
-
- for (int i = 0; i < n; i++) {
- Object* elt = elements->get(i);
- if (!elt->IsString()) return isolate->heap()->undefined_value();
- String* element = String::cast(elt);
- if (!element->IsFlat()) return isolate->heap()->undefined_value();
- total_length += element->length();
- if (ascii && element->IsTwoByteRepresentation()) {
- ascii = false;
- }
- }
-
- int worst_case_length =
- kSpaceForBrackets + n * kSpaceForQuotesAndComma
- + total_length * kJsonQuoteWorstCaseBlowup;
-
- if (worst_case_length > kMaxGuaranteedNewSpaceString) {
- return isolate->heap()->undefined_value();
- }
-
- if (ascii) {
- return QuoteJsonStringArray<char, SeqOneByteString>(isolate,
- elements,
- worst_case_length);
- } else {
- return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
- elements,
- worst_case_length);
- }
+ return BasicJsonStringifier::StringifyString(isolate, string);
}
@@ -6134,6 +5776,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
}
+// ES6 draft 9.1.11
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
+ NoHandleAllocation ha(isolate);
+ ASSERT(args.length() == 1);
+
+ CONVERT_DOUBLE_ARG_CHECKED(number, 0);
+
+ // We do not include 0 so that we don't have to treat +0 / -0 cases.
+ if (number > 0 && number <= Smi::kMaxValue) {
+ return Smi::FromInt(static_cast<int>(number));
+ }
+ if (number <= 0) {
+ return Smi::FromInt(0);
+ }
+ return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
NoHandleAllocation ha(isolate);
ASSERT(args.length() == 1);
@@ -9015,7 +8675,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
// and return the compiled function bound in the local context.
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
source,
- Handle<Context>(isolate->context()),
+ context,
context->IsNativeContext(),
language_mode,
NO_PARSE_RESTRICTION,
@@ -9085,8 +8745,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
RUNTIME_ASSERT(IsAligned(size, kPointerSize));
RUNTIME_ASSERT(size > 0);
Heap* heap = isolate->heap();
- const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
- RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
+ RUNTIME_ASSERT(size <= heap->MaxNewSpaceAllocationSize());
Object* allocation;
{ MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
if (maybe_allocation->ToObject(&allocation)) {
@@ -9896,9 +9555,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
// Returns an array that tells you where in the [0, length) interval an array
-// might have elements. Can either return keys (positive integers) or
-// intervals (pair of a negative integer (-start-1) followed by a
-// positive (length)) or undefined values.
+// might have elements. Can either return an array of keys (positive integers
+// or undefined) or a number representing the positive length of an interval
+// starting at index 0.
// Intervals can span over some keys that are not in the object.
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
HandleScope scope(isolate);
@@ -9906,37 +9565,34 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
if (array->elements()->IsDictionary()) {
- // Create an array and get all the keys into it, then remove all the
- // keys that are not integers in the range 0 to length-1.
- bool threw = false;
- Handle<FixedArray> keys =
- GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
- if (threw) return Failure::Exception();
-
- int keys_length = keys->length();
- for (int i = 0; i < keys_length; i++) {
- Object* key = keys->get(i);
- uint32_t index = 0;
- if (!key->ToArrayIndex(&index) || index >= length) {
- // Zap invalid keys.
- keys->set_undefined(i);
+ Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
+ for (Handle<Object> p = array;
+ !p->IsNull();
+ p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
+ if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
+ // Bail out if we find a proxy or interceptor, likely not worth
+ // collecting keys in that case.
+ return *isolate->factory()->NewNumberFromUint(length);
}
+ Handle<JSObject> current = Handle<JSObject>::cast(p);
+ Handle<FixedArray> current_keys =
+ isolate->factory()->NewFixedArray(
+ current->NumberOfLocalElements(NONE));
+ current->GetLocalElementKeys(*current_keys, NONE);
+ keys = UnionOfKeys(keys, current_keys);
+ }
+ // Erase any keys >= length.
+ // TODO(adamk): Remove this step when the contract of %GetArrayKeys
+ // is changed to let this happen on the JS side.
+ for (int i = 0; i < keys->length(); i++) {
+ if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
}
return *isolate->factory()->NewJSArrayWithElements(keys);
} else {
ASSERT(array->HasFastSmiOrObjectElements() ||
array->HasFastDoubleElements());
- Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
- // -1 means start of array.
- single_interval->set(0, Smi::FromInt(-1));
- FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
- uint32_t actual_length =
- static_cast<uint32_t>(elements->length());
- uint32_t min_length = actual_length < length ? actual_length : length;
- Handle<Object> length_object =
- isolate->factory()->NewNumber(static_cast<double>(min_length));
- single_interval->set(1, *length_object);
- return *isolate->factory()->NewJSArrayWithElements(single_interval);
+ uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
+ return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
}
}
@@ -11811,6 +11467,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
}
+static bool IsBlockOrCatchOrWithScope(ScopeIterator::ScopeType type) {
+ return type == ScopeIterator::ScopeTypeBlock ||
+ type == ScopeIterator::ScopeTypeCatch ||
+ type == ScopeIterator::ScopeTypeWith;
+}
+
+
// Creates a copy of the with context chain. The copy of the context chain is
// is linked to the function context supplied.
static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
@@ -11825,8 +11488,7 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
ScopeIterator it(isolate, frame, inlined_jsframe_index);
if (it.Failed()) return Handle<Context>::null();
- for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
- it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
+ for ( ; IsBlockOrCatchOrWithScope(it.Type()); it.Next()) {
ASSERT(!it.Done());
scope_chain.Add(it.CurrentScopeInfo());
context_chain.Add(it.CurrentContext());
@@ -11842,6 +11504,7 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
ASSERT(!(scope_info->HasContext() & current.is_null()));
if (scope_info->Type() == CATCH_SCOPE) {
+ ASSERT(current->IsCatchContext());
Handle<String> name(String::cast(current->extension()));
Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX),
isolate);
@@ -11852,6 +11515,7 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
thrown_object);
} else if (scope_info->Type() == BLOCK_SCOPE) {
// Materialize the contents of the block scope into a JSObject.
+ ASSERT(current->IsBlockContext());
Handle<JSObject> block_scope_object =
MaterializeBlockScope(isolate, current);
CHECK(!block_scope_object.is_null());
@@ -11904,37 +11568,65 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
}
}
- Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
- int length = frame_inspector->GetParametersCount();
- Handle<JSObject> arguments =
- isolate->factory()->NewArgumentsObject(function, length);
- Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
+ // FunctionGetArguments can't return a non-Object.
+ return Handle<JSObject>(JSObject::cast(
+ Accessors::FunctionGetArguments(frame_inspector->GetFunction(),
+ NULL)->ToObjectUnchecked()), isolate);
+}
- AssertNoAllocation no_gc;
- WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
- for (int i = 0; i < length; i++) {
- array->set(i, frame_inspector->GetParameter(i), mode);
+
+// Compile and evaluate source for the given context.
+static MaybeObject* DebugEvaluate(Isolate* isolate,
+ Handle<Context> context,
+ Handle<Object> context_extension,
+ Handle<Object> receiver,
+ Handle<String> source) {
+ if (context_extension->IsJSObject()) {
+ Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
+ Handle<JSFunction> closure(context->closure(), isolate);
+ context = isolate->factory()->NewWithContext(closure, context, extension);
}
- arguments->set_elements(*array);
- return arguments;
-}
+ Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
+ source,
+ context,
+ context->IsNativeContext(),
+ CLASSIC_MODE,
+ NO_PARSE_RESTRICTION,
+ RelocInfo::kNoPosition);
+ if (shared.is_null()) return Failure::Exception();
-static const char kSourceStr[] =
- "(function(arguments,__source__){return eval(__source__);})";
+ Handle<JSFunction> eval_fun =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ shared, context, NOT_TENURED);
+ bool pending_exception;
+ Handle<Object> result = Execution::Call(
+ eval_fun, receiver, 0, NULL, &pending_exception);
+
+ if (pending_exception) return Failure::Exception();
+
+ // Skip the global proxy as it has no properties and always delegates to the
+ // real global object.
+ if (result->IsJSGlobalProxy()) {
+ result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
+ }
+
+ // Clear the oneshot breakpoints so that the debugger does not step further.
+ isolate->debug()->ClearStepping();
+ return *result;
+}
// Evaluate a piece of JavaScript in the context of a stack frame for
-// debugging. This is accomplished by creating a new context which in its
-// extension part has all the parameters and locals of the function on the
-// stack frame. A function which calls eval with the code to evaluate is then
-// compiled in this context and called in this context. As this context
-// replaces the context of the function on the stack frame a new (empty)
-// function is created as well to be used as the closure for the context.
-// This function and the context acts as replacements for the function on the
-// stack frame presenting the same view of the values of parameters and
-// local variables as if the piece of JavaScript was evaluated at the point
-// where the function on the stack frame is currently stopped.
+// debugging. This is done by creating a new context which in its extension
+// part has all the parameters and locals of the function on the stack frame
+// as well as a materialized arguments object. As this context replaces
+// the context of the function on the stack frame a new (empty) function
+// is created as well to be used as the closure for the context.
+// This closure as replacements for the one on the stack frame presenting
+// the same view of the values of parameters and local variables as if the
+// piece of JavaScript was evaluated at the point where the function on the
+// stack frame is currently stopped when we compile and run the (direct) eval.
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
HandleScope scope(isolate);
@@ -11942,17 +11634,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
// evaluated.
ASSERT(args.length() == 6);
Object* check_result;
- { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
+ { MaybeObject* maybe_result = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check_result->ToObject(&check_result)) {
- return maybe_check_result;
- }
+ if (!maybe_result->ToObject(&check_result)) return maybe_result;
}
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
- Handle<Object> additional_context(args[5], isolate);
+ Handle<Object> context_extension(args[5], isolate);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
@@ -11963,7 +11653,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
JavaScriptFrame* frame = it.frame();
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
- Handle<ScopeInfo> scope_info(function->shared()->scope_info());
// Traverse the saved contexts chain to find the active context for the
// selected frame.
@@ -11988,28 +11677,42 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
ASSERT(go_between_scope_info->ContextLocalCount() == 0);
#endif
- // Materialize the content of the local scope into a JSObject.
+ // Materialize the content of the local scope including the arguments object.
Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
isolate, frame, &frame_inspector);
RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
+ // Do not materialize the arguments object for eval or top-level code.
+ if (function->shared()->is_function()) {
+ Handle<Context> frame_context(Context::cast(frame->context()));
+ Handle<Context> function_context;
+ Handle<ScopeInfo> scope_info(function->shared()->scope_info());
+ if (scope_info->HasContext()) {
+ function_context = Handle<Context>(frame_context->declaration_context());
+ }
+ Handle<Object> arguments = GetArgumentsObject(isolate,
+ frame,
+ &frame_inspector,
+ scope_info,
+ function_context);
+ SetProperty(isolate,
+ local_scope,
+ isolate->factory()->arguments_string(),
+ arguments,
+ ::NONE,
+ kNonStrictMode);
+ }
+
// Allocate a new context for the debug evaluation and set the extension
// object build.
- Handle<Context> context =
- isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
- go_between);
+ Handle<Context> context = isolate->factory()->NewFunctionContext(
+ Context::MIN_CONTEXT_SLOTS, go_between);
// Use the materialized local scope in a with context.
context =
isolate->factory()->NewWithContext(go_between, context, local_scope);
// Copy any with contexts present and chain them in front of this context.
- Handle<Context> frame_context(Context::cast(frame->context()));
- Handle<Context> function_context;
- // Get the function's context if it has one.
- if (scope_info->HasContext()) {
- function_context = Handle<Context>(frame_context->declaration_context());
- }
context = CopyNestedScopeContextChain(isolate,
go_between,
context,
@@ -12022,79 +11725,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
return exception;
}
- if (additional_context->IsJSObject()) {
- Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
- context =
- isolate->factory()->NewWithContext(go_between, context, extension);
- }
-
- // Wrap the evaluation statement in a new function compiled in the newly
- // created context. The function has one parameter which has to be called
- // 'arguments'. This it to have access to what would have been 'arguments' in
- // the function being debugged.
- // function(arguments,__source__) {return eval(__source__);}
-
- Handle<String> function_source =
- isolate->factory()->NewStringFromAscii(
- Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
-
- // Currently, the eval code will be executed in non-strict mode,
- // even in the strict code context.
- Handle<SharedFunctionInfo> shared =
- Compiler::CompileEval(function_source,
- context,
- context->IsNativeContext(),
- CLASSIC_MODE,
- NO_PARSE_RESTRICTION,
- RelocInfo::kNoPosition);
- if (shared.is_null()) return Failure::Exception();
- Handle<JSFunction> compiled_function =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
-
- // Invoke the result of the compilation to get the evaluation function.
- bool has_pending_exception;
Handle<Object> receiver(frame->receiver(), isolate);
- Handle<Object> evaluation_function =
- Execution::Call(compiled_function, receiver, 0, NULL,
- &has_pending_exception);
- if (has_pending_exception) return Failure::Exception();
-
- Handle<Object> arguments = GetArgumentsObject(isolate,
- frame,
- &frame_inspector,
- scope_info,
- function_context);
-
- // Check if eval is blocked in the context and temporarily allow it
- // for debugger.
- Handle<Context> native_context = Handle<Context>(context->native_context());
- bool eval_disabled =
- native_context->allow_code_gen_from_strings()->IsFalse();
- if (eval_disabled) {
- native_context->set_allow_code_gen_from_strings(
- isolate->heap()->true_value());
- }
- // Invoke the evaluation function and return the result.
- Handle<Object> argv[] = { arguments, source };
- Handle<Object> result =
- Execution::Call(Handle<JSFunction>::cast(evaluation_function),
- receiver,
- ARRAY_SIZE(argv),
- argv,
- &has_pending_exception);
- if (eval_disabled) {
- native_context->set_allow_code_gen_from_strings(
- isolate->heap()->false_value());
- }
- if (has_pending_exception) return Failure::Exception();
-
- // Skip the global proxy as it has no properties and always delegates to the
- // real global object.
- if (result->IsJSGlobalProxy()) {
- result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
- }
-
- return *result;
+ return DebugEvaluate(isolate, context, context_extension, receiver, source);
}
@@ -12105,15 +11737,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
// evaluated.
ASSERT(args.length() == 4);
Object* check_result;
- { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
+ { MaybeObject* maybe_result = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check_result->ToObject(&check_result)) {
- return maybe_check_result;
- }
+ if (!maybe_result->ToObject(&check_result)) return maybe_result;
}
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
- Handle<Object> additional_context(args[3], isolate);
+ Handle<Object> context_extension(args[3], isolate);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
@@ -12131,45 +11761,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
// Get the native context now set to the top context from before the
// debugger was invoked.
Handle<Context> context = isolate->native_context();
-
- bool is_global = true;
-
- if (additional_context->IsJSObject()) {
- // Create a new with context with the additional context information between
- // the context of the debugged function and the eval code to be executed.
- context = isolate->factory()->NewWithContext(
- Handle<JSFunction>(context->closure()),
- context,
- Handle<JSObject>::cast(additional_context));
- is_global = false;
- }
-
- // Compile the source to be evaluated.
- // Currently, the eval code will be executed in non-strict mode,
- // even in the strict code context.
- Handle<SharedFunctionInfo> shared =
- Compiler::CompileEval(source,
- context,
- is_global,
- CLASSIC_MODE,
- NO_PARSE_RESTRICTION,
- RelocInfo::kNoPosition);
- if (shared.is_null()) return Failure::Exception();
- Handle<JSFunction> compiled_function =
- Handle<JSFunction>(
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context));
-
- // Invoke the result of the compilation to get the evaluation function.
- bool has_pending_exception;
Handle<Object> receiver = isolate->global_object();
- Handle<Object> result =
- Execution::Call(compiled_function, receiver, 0, NULL,
- &has_pending_exception);
- // Clear the oneshot breakpoints so that the debugger does not step further.
- isolate->debug()->ClearStepping();
- if (has_pending_exception) return Failure::Exception();
- return *result;
+ return DebugEvaluate(isolate, context, context_extension, receiver, source);
}
@@ -13247,7 +12840,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
if (obj->IsJSGlobalProxy()) {
Object* proto = obj->GetPrototype();
- if (obj->IsNull()) return isolate->heap()->false_value();
+ if (proto->IsNull()) return isolate->heap()->false_value();
ASSERT(proto->IsJSGlobalObject());
obj = JSReceiver::cast(proto);
}
@@ -13262,7 +12855,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
CONVERT_BOOLEAN_ARG_CHECKED(is_observed, 1);
if (obj->IsJSGlobalProxy()) {
Object* proto = obj->GetPrototype();
- if (obj->IsNull()) return isolate->heap()->undefined_value();
+ if (proto->IsNull()) return isolate->heap()->undefined_value();
ASSERT(proto->IsJSGlobalObject());
obj = JSReceiver::cast(proto);
}
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index 2959fedc5..b16acd1d8 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -55,7 +55,7 @@ namespace internal {
F(IsPropertyEnumerable, 2, 1) \
F(GetPropertyNames, 1, 1) \
F(GetPropertyNamesFast, 1, 1) \
- F(GetLocalPropertyNames, 1, 1) \
+ F(GetLocalPropertyNames, 2, 1) \
F(GetLocalElementNames, 1, 1) \
F(GetInterceptorInfo, 1, 1) \
F(GetNamedInterceptorPropertyNames, 1, 1) \
@@ -129,6 +129,7 @@ namespace internal {
F(NumberToString, 1, 1) \
F(NumberToStringSkipCache, 1, 1) \
F(NumberToInteger, 1, 1) \
+ F(NumberToPositiveInteger, 1, 1) \
F(NumberToIntegerMapMinusZero, 1, 1) \
F(NumberToJSUint32, 1, 1) \
F(NumberToJSInt32, 1, 1) \
@@ -195,8 +196,6 @@ namespace internal {
F(ParseJson, 1, 1) \
F(BasicJSONStringify, 1, 1) \
F(QuoteJSONString, 1, 1) \
- F(QuoteJSONStringComma, 1, 1) \
- F(QuoteJSONStringArray, 1, 1) \
\
/* Strings */ \
F(StringCharCodeAt, 2, 1) \
@@ -299,7 +298,8 @@ namespace internal {
F(IsJSModule, 1, 1) \
\
/* Harmony symbols */ \
- F(CreateSymbol, 0, 1) \
+ F(CreateSymbol, 1, 1) \
+ F(SymbolName, 1, 1) \
\
/* Harmony proxies */ \
F(CreateJSProxy, 2, 1) \
@@ -341,6 +341,11 @@ namespace internal {
F(ObservationWeakMapCreate, 0, 1) \
F(UnwrapGlobalProxy, 1, 1) \
\
+ /* Harmony typed arrays */ \
+ F(ArrayBufferInitialize, 2, 1)\
+ F(ArrayBufferGetByteLength, 1, 1)\
+ F(ArrayBufferSliceImpl, 3, 1) \
+ \
/* Statements */ \
F(NewClosure, 3, 1) \
F(NewObject, 1, 1) \
@@ -514,7 +519,6 @@ namespace internal {
#define INLINE_FUNCTION_LIST(F) \
F(IsSmi, 1, 1) \
F(IsNonNegativeSmi, 1, 1) \
- F(IsSymbol, 1, 1) \
F(IsArray, 1, 1) \
F(IsRegExp, 1, 1) \
F(IsConstructCall, 0, 1) \
diff --git a/deps/v8/src/runtime.js b/deps/v8/src/runtime.js
index 09b39ffe1..22f888d81 100644
--- a/deps/v8/src/runtime.js
+++ b/deps/v8/src/runtime.js
@@ -69,16 +69,24 @@ function EQUALS(y) {
} else if (IS_STRING(x)) {
while (true) {
if (IS_STRING(y)) return %StringEquals(x, y);
+ if (IS_SYMBOL(y)) return 1; // not equal
if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
y = %ToPrimitive(y, NO_HINT);
}
+ } else if (IS_SYMBOL(x)) {
+ while (true) {
+ if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
+ if (!IS_SPEC_OBJECT(y)) return 1; // not equal
+ y = %ToPrimitive(y, NO_HINT);
+ }
} else if (IS_BOOLEAN(x)) {
if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
if (IS_NULL_OR_UNDEFINED(y)) return 1;
if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
+ if (IS_SYMBOL(y)) return 1; // not equal
// y is object.
x = %ToNumber(x);
y = %ToPrimitive(y, NO_HINT);
@@ -508,6 +516,7 @@ function ToPrimitive(x, hint) {
if (IS_STRING(x)) return x;
// Normal behavior.
if (!IS_SPEC_OBJECT(x)) return x;
+ if (IS_SYMBOL_WRAPPER(x)) return %_ValueOf(x);
if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
}
@@ -532,6 +541,7 @@ function ToNumber(x) {
}
if (IS_BOOLEAN(x)) return x ? 1 : 0;
if (IS_UNDEFINED(x)) return $NaN;
+ if (IS_SYMBOL(x)) return $NaN;
return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
}
@@ -542,6 +552,7 @@ function NonNumberToNumber(x) {
}
if (IS_BOOLEAN(x)) return x ? 1 : 0;
if (IS_UNDEFINED(x)) return $NaN;
+ if (IS_SYMBOL(x)) return $NaN;
return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
}
@@ -572,6 +583,7 @@ function ToName(x) {
// ECMA-262, section 9.9, page 36.
function ToObject(x) {
if (IS_STRING(x)) return new $String(x);
+ if (IS_SYMBOL(x)) return new $Symbol(x);
if (IS_NUMBER(x)) return new $Number(x);
if (IS_BOOLEAN(x)) return new $Boolean(x);
if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc
index bd2db5818..ef2dc2c64 100755
--- a/deps/v8/src/scanner.cc
+++ b/deps/v8/src/scanner.cc
@@ -877,7 +877,7 @@ uc32 Scanner::ScanIdentifierUnicodeEscape() {
KEYWORD("while", Token::WHILE) \
KEYWORD("with", Token::WITH) \
KEYWORD_GROUP('y') \
- KEYWORD("yield", Token::FUTURE_STRICT_RESERVED_WORD)
+ KEYWORD("yield", Token::YIELD)
static Token::Value KeywordOrIdentifierToken(const char* input,
diff --git a/deps/v8/src/scanner.h b/deps/v8/src/scanner.h
index a454750de..dd1bfb8bf 100644
--- a/deps/v8/src/scanner.h
+++ b/deps/v8/src/scanner.h
@@ -53,7 +53,8 @@ enum ParsingFlags {
kLanguageModeMask = 0x03,
kAllowLazy = 0x04,
kAllowNativesSyntax = 0x08,
- kAllowModules = 0x10
+ kAllowModules = 0x10,
+ kAllowGenerators = 0x20
};
STATIC_ASSERT((kLanguageModeMask & CLASSIC_MODE) == CLASSIC_MODE);
diff --git a/deps/v8/src/spaces-inl.h b/deps/v8/src/spaces-inl.h
index aeac570f4..77117b8a4 100644
--- a/deps/v8/src/spaces-inl.h
+++ b/deps/v8/src/spaces-inl.h
@@ -351,23 +351,6 @@ intptr_t LargeObjectSpace::Available() {
}
-template <typename StringType>
-void NewSpace::ShrinkStringAtAllocationBoundary(String* string, int length) {
- ASSERT(length <= string->length());
- ASSERT(string->IsSeqString());
- ASSERT(string->address() + StringType::SizeFor(string->length()) ==
- allocation_info_.top);
- Address old_top = allocation_info_.top;
- allocation_info_.top =
- string->address() + StringType::SizeFor(length);
- string->set_length(length);
- if (Marking::IsBlack(Marking::MarkBitFrom(string))) {
- int delta = static_cast<int>(old_top - allocation_info_.top);
- MemoryChunk::IncrementLiveBytesFromMutator(string->address(), -delta);
- }
-}
-
-
bool FreeListNode::IsFreeListNode(HeapObject* object) {
Map* map = object->map();
Heap* heap = object->GetHeap();
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc
index 2952fd52c..f8e6a1e87 100644
--- a/deps/v8/src/spaces.cc
+++ b/deps/v8/src/spaces.cc
@@ -1030,10 +1030,10 @@ intptr_t PagedSpace::SizeOfFirstPage() {
size = 16 * kPointerSize * KB;
break;
case CODE_SPACE:
- if (kPointerSize == 8) {
- // On x64 we allocate code pages in a special way (from the reserved
- // 2Byte area). That part of the code is not yet upgraded to handle
- // small pages.
+ if (heap()->isolate()->code_range()->exists()) {
+ // When code range exists, code pages are allocated in a special way
+ // (from the reserved code range). That part of the code is not yet
+ // upgraded to handle small pages.
size = AreaSize();
} else {
size = 384 * KB;
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
index 39c19a4e3..65eefd015 100644
--- a/deps/v8/src/spaces.h
+++ b/deps/v8/src/spaces.h
@@ -2419,11 +2419,6 @@ class NewSpace : public Space {
virtual bool ReserveSpace(int bytes);
- // Resizes a sequential string which must be the most recent thing that was
- // allocated in new space.
- template <typename StringType>
- inline void ShrinkStringAtAllocationBoundary(String* string, int len);
-
#ifdef VERIFY_HEAP
// Verify the active semispace.
virtual void Verify();
diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc
index a0d98e27d..553c6f509 100644
--- a/deps/v8/src/stub-cache.cc
+++ b/deps/v8/src/stub-cache.cc
@@ -123,10 +123,13 @@ Handle<Code> StubCache::FindIC(Handle<Name> name,
Handle<Code> StubCache::FindHandler(Handle<Name> name,
+ Handle<JSObject> receiver,
Handle<JSObject> stub_holder,
Code::Kind kind,
- Code::StubType type,
- Code::ExtraICState extra_ic_state) {
+ Code::StubType type) {
+ Code::ExtraICState extra_ic_state = Code::ComputeExtraICState(
+ receiver.is_identical_to(stub_holder) ? Code::OWN_STUB
+ : Code::PROTOTYPE_STUB);
ASSERT(type != Code::NORMAL);
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::STUB, extra_ic_state, type, kind);
@@ -194,7 +197,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
// Compile the stub that is either shared for all names or
// name specific if there are global objects involved.
Handle<Code> handler = FindHandler(
- cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
+ cache_name, receiver, receiver, Code::LOAD_IC, Code::NONEXISTENT);
if (!handler.is_null()) return handler;
LoadStubCompiler compiler(isolate_);
@@ -218,7 +221,7 @@ Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::LOAD_IC, Code::FIELD);
+ name, receiver, stub_holder, Code::LOAD_IC, Code::FIELD);
if (!stub.is_null()) return stub;
LoadStubCompiler compiler(isolate_);
@@ -237,7 +240,7 @@ Handle<Code> StubCache::ComputeLoadCallback(
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
+ name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
LoadStubCompiler compiler(isolate_);
@@ -254,7 +257,7 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
Handle<JSFunction> getter) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
+ name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
LoadStubCompiler compiler(isolate_);
@@ -271,7 +274,7 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
Handle<JSFunction> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> handler = FindHandler(
- name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
+ name, receiver, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
if (!handler.is_null()) return handler;
LoadStubCompiler compiler(isolate_);
@@ -287,7 +290,7 @@ Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
+ name, receiver, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
if (!stub.is_null()) return stub;
LoadStubCompiler compiler(isolate_);
@@ -334,7 +337,7 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
+ name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
if (!stub.is_null()) return stub;
KeyedLoadStubCompiler compiler(isolate_);
@@ -351,7 +354,8 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSFunction> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> handler = FindHandler(
- name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
+ name, receiver, stub_holder, Code::KEYED_LOAD_IC,
+ Code::CONSTANT_FUNCTION);
if (!handler.is_null()) return handler;
KeyedLoadStubCompiler compiler(isolate_);
@@ -366,7 +370,7 @@ Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
+ name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
if (!stub.is_null()) return stub;
KeyedLoadStubCompiler compiler(isolate_);
@@ -384,7 +388,7 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<ExecutableAccessorInfo> callback) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindHandler(
- name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
+ name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
KeyedLoadStubCompiler compiler(isolate_);
@@ -397,7 +401,7 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
Handle<JSObject> receiver,
- int field_index,
+ LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode) {
Code::StubType type =
@@ -409,7 +413,7 @@ Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code =
- compiler.CompileStoreField(receiver, field_index, transition, name);
+ compiler.CompileStoreField(receiver, lookup, transition, name);
JSObject::UpdateMapCodeCache(receiver, name, code);
return code;
}
@@ -441,7 +445,9 @@ Handle<Code> StubCache::ComputeKeyedStoreElement(
Code::KEYED_STORE_IC, extra_state);
ASSERT(store_mode == STANDARD_STORE ||
- store_mode == STORE_AND_GROW_NO_TRANSITION);
+ store_mode == STORE_AND_GROW_NO_TRANSITION ||
+ store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
+ store_mode == STORE_NO_TRANSITION_HANDLE_COW);
Handle<String> name =
isolate()->factory()->KeyedStoreElementMonomorphic_string();
@@ -530,7 +536,7 @@ Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
Handle<JSObject> receiver,
- int field_index,
+ LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode) {
Code::StubType type =
@@ -541,7 +547,7 @@ Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
Handle<Code> code =
- compiler.CompileStoreField(receiver, field_index, transition, name);
+ compiler.CompileStoreField(receiver, lookup, transition, name);
JSObject::UpdateMapCodeCache(receiver, name, code);
return code;
}
@@ -899,7 +905,9 @@ Handle<Code> StubCache::ComputeStoreElementPolymorphic(
KeyedAccessStoreMode store_mode,
StrictModeFlag strict_mode) {
ASSERT(store_mode == STANDARD_STORE ||
- store_mode == STORE_AND_GROW_NO_TRANSITION);
+ store_mode == STORE_AND_GROW_NO_TRANSITION ||
+ store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
+ store_mode == STORE_NO_TRANSITION_HANDLE_COW);
Handle<PolymorphicCodeCache> cache =
isolate_->factory()->polymorphic_code_cache();
Code::ExtraICState extra_state = Code::ComputeExtraICState(store_mode,
@@ -1580,7 +1588,7 @@ Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name) {
Label miss, miss_restore_name;
@@ -1590,7 +1598,7 @@ Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
// Generate store field code.
GenerateStoreField(masm(),
object,
- index,
+ lookup,
transition,
name,
receiver(), this->name(), value(), scratch1(), scratch2(),
@@ -1660,10 +1668,19 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) {
ElementsKind elements_kind = receiver_map->elements_kind();
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
- Handle<Code> stub =
- KeyedStoreElementStub(is_jsarray,
- elements_kind,
- store_mode_).GetCode(isolate());
+ Handle<Code> stub;
+ if (FLAG_compiled_keyed_stores &&
+ (receiver_map->has_fast_elements() ||
+ receiver_map->has_external_array_elements())) {
+ stub = KeyedStoreFastElementStub(
+ is_jsarray,
+ elements_kind,
+ store_mode_).GetCode(isolate());
+ } else {
+ stub = KeyedStoreElementStub(is_jsarray,
+ elements_kind,
+ store_mode_).GetCode(isolate());
+ }
__ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
@@ -1809,10 +1826,19 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
strict_mode(),
store_mode_).GetCode(isolate());
} else {
- cached_stub = KeyedStoreElementStub(
- is_js_array,
- elements_kind,
- store_mode_).GetCode(isolate());
+ if (FLAG_compiled_keyed_stores &&
+ (receiver_map->has_fast_elements() ||
+ receiver_map->has_external_array_elements())) {
+ cached_stub = KeyedStoreFastElementStub(
+ is_js_array,
+ elements_kind,
+ store_mode_).GetCode(isolate());
+ } else {
+ cached_stub = KeyedStoreElementStub(
+ is_js_array,
+ elements_kind,
+ store_mode_).GetCode(isolate());
+ }
}
ASSERT(!cached_stub.is_null());
handlers.Add(cached_stub);
diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h
index 7c455664c..bca3b7bca 100644
--- a/deps/v8/src/stub-cache.h
+++ b/deps/v8/src/stub-cache.h
@@ -85,10 +85,10 @@ class StubCache {
Handle<Code> FindHandler(
Handle<Name> name,
+ Handle<JSObject> receiver,
Handle<JSObject> stub_holder,
Code::Kind kind,
- Code::StubType type,
- Code::ExtraICState extra_state = Code::kNoExtraICState);
+ Code::StubType type);
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
@@ -161,7 +161,7 @@ class StubCache {
Handle<Code> ComputeStoreField(Handle<Name> name,
Handle<JSObject> object,
- int field_index,
+ LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode);
@@ -192,7 +192,7 @@ class StubCache {
Handle<Code> ComputeKeyedStoreField(Handle<Name> name,
Handle<JSObject> object,
- int field_index,
+ LookupResult* lookup,
Handle<Map> transition,
StrictModeFlag strict_mode);
@@ -511,7 +511,7 @@ class StubCompiler BASE_EMBEDDED {
void GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
@@ -782,7 +782,7 @@ class BaseStoreStubCompiler: public StubCompiler {
virtual ~BaseStoreStubCompiler() { }
Handle<Code> CompileStoreField(Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name);
diff --git a/deps/v8/src/symbol.js b/deps/v8/src/symbol.js
index b7f9dc949..fb7476f43 100644
--- a/deps/v8/src/symbol.js
+++ b/deps/v8/src/symbol.js
@@ -27,13 +27,55 @@
"use strict";
-var $Symbol = function() { return %CreateSymbol() }
-global.Symbol = $Symbol
+var $Symbol = global.Symbol;
-// Symbols only have a toString method and no prototype.
-var SymbolDelegate = {
- __proto__: null,
- toString: $Object.prototype.toString
+function SymbolConstructor(x) {
+ var value =
+ IS_SYMBOL(x) ? x : %CreateSymbol(IS_UNDEFINED(x) ? x : ToString(x));
+ if (%_IsConstructCall()) {
+ %_SetValueOf(this, value);
+ } else {
+ return value;
+ }
}
-$Object.freeze(SymbolDelegate)
+function SymbolGetName() {
+ var symbol = IS_SYMBOL_WRAPPER(this) ? %_ValueOf(this) : this;
+ if (!IS_SYMBOL(symbol)) {
+ throw MakeTypeError(
+ 'incompatible_method_receiver', ["Symbol.prototype.name", this]);
+ }
+ return %SymbolName(symbol);
+}
+
+function SymbolToString() {
+ throw MakeTypeError('symbol_to_string');
+}
+
+function SymbolValueOf() {
+ // NOTE: Both Symbol objects and values can enter here as
+ // 'this'. This is not as dictated by ECMA-262.
+ if (!IS_SYMBOL(this) && !IS_SYMBOL_WRAPPER(this)) {
+ throw MakeTypeError(
+ 'incompatible_method_receiver', ["Symbol.prototype.valueOf", this]);
+ }
+ return %_ValueOf(this);
+}
+
+//-------------------------------------------------------------------
+
+function SetUpSymbol() {
+ %CheckIsBootstrapping();
+
+ %SetCode($Symbol, SymbolConstructor);
+ %FunctionSetPrototype($Symbol, new $Symbol());
+ %SetProperty($Symbol.prototype, "constructor", $Symbol, DONT_ENUM);
+
+ InstallGetter($Symbol.prototype, "name", SymbolGetName);
+ InstallFunctions($Symbol.prototype, DONT_ENUM, $Array(
+ "toString", SymbolToString,
+ "valueOf", SymbolValueOf
+ ));
+}
+
+SetUpSymbol();
diff --git a/deps/v8/src/token.h b/deps/v8/src/token.h
index 4078a15cd..04d7f7639 100644
--- a/deps/v8/src/token.h
+++ b/deps/v8/src/token.h
@@ -174,6 +174,7 @@ namespace internal {
K(EXPORT, "export", 0) \
K(IMPORT, "import", 0) \
K(LET, "let", 0) \
+ K(YIELD, "yield", 0) \
\
/* Illegal token - not able to scan. */ \
T(ILLEGAL, "ILLEGAL", 0) \
diff --git a/deps/v8/src/type-info.cc b/deps/v8/src/type-info.cc
index 6ac05547a..39a01f59e 100644
--- a/deps/v8/src/type-info.cc
+++ b/deps/v8/src/type-info.cc
@@ -126,9 +126,9 @@ bool TypeFeedbackOracle::StoreIsMonomorphicNormal(TypeFeedbackId ast_id) {
if (map_or_code->IsMap()) return true;
if (map_or_code->IsCode()) {
Handle<Code> code = Handle<Code>::cast(map_or_code);
- bool standard_store =
- Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
- STANDARD_STORE;
+ bool standard_store = FLAG_compiled_keyed_stores ||
+ (Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
+ STANDARD_STORE);
bool preliminary_checks =
code->is_keyed_store_stub() &&
standard_store &&
@@ -146,9 +146,9 @@ bool TypeFeedbackOracle::StoreIsPolymorphic(TypeFeedbackId ast_id) {
Handle<Object> map_or_code = GetInfo(ast_id);
if (map_or_code->IsCode()) {
Handle<Code> code = Handle<Code>::cast(map_or_code);
- bool standard_store =
- Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
- STANDARD_STORE;
+ bool standard_store = FLAG_compiled_keyed_stores ||
+ (Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
+ STANDARD_STORE);
return code->is_keyed_store_stub() && standard_store &&
code->ic_state() == POLYMORPHIC;
}
@@ -283,11 +283,12 @@ Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
case RECEIVER_MAP_CHECK:
UNREACHABLE();
break;
- case SYMBOL_CHECK:
- return Handle<JSObject>(native_context_->symbol_delegate());
case STRING_CHECK:
function = native_context_->string_function();
break;
+ case SYMBOL_CHECK:
+ function = native_context_->symbol_function();
+ break;
case NUMBER_CHECK:
function = native_context_->number_function();
break;
diff --git a/deps/v8/src/typedarray.js b/deps/v8/src/typedarray.js
new file mode 100644
index 000000000..c3e3ebd66
--- /dev/null
+++ b/deps/v8/src/typedarray.js
@@ -0,0 +1,98 @@
+// Copyright 2013 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.
+
+"use strict";
+
+var $ArrayBuffer = global.__ArrayBuffer;
+
+function ArrayBufferConstructor(byteLength) { // length = 1
+ if (%_IsConstructCall()) {
+ var l = TO_POSITIVE_INTEGER(byteLength);
+ %ArrayBufferInitialize(this, l);
+ } else {
+ return new $ArrayBuffer(byteLength);
+ }
+}
+
+function ArrayBufferGetByteLength() {
+ if (!IS_ARRAYBUFFER(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['ArrayBuffer.prototype.byteLength', this]);
+ }
+ return %ArrayBufferGetByteLength(this);
+}
+
+// ES6 Draft 15.13.5.5.3
+function ArrayBufferSlice(start, end) {
+ if (!IS_ARRAYBUFFER(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['ArrayBuffer.prototype.slice', this]);
+ }
+
+ var relativeStart = TO_INTEGER(start);
+ var first;
+ if (relativeStart < 0) {
+ first = MathMax(this.byteLength + relativeStart, 0);
+ } else {
+ first = MathMin(relativeStart, this.byteLength);
+ }
+ var relativeEnd = IS_UNDEFINED(end) ? this.byteLength : TO_INTEGER(end);
+ var fin;
+ if (relativeEnd < 0) {
+ fin = MathMax(this.byteLength + relativeEnd, 0);
+ } else {
+ fin = MathMin(relativeEnd, this.byteLength);
+ }
+
+ var newLen = fin - first;
+ // TODO(dslomov): implement inheritance
+ var result = new $ArrayBuffer(newLen);
+
+ %ArrayBufferSliceImpl(this, result, first);
+ return result;
+}
+
+
+
+// -------------------------------------------------------------------
+
+(function () {
+ %CheckIsBootstrapping();
+
+ // Set up the Uint16Array constructor function.
+ %SetCode($ArrayBuffer, ArrayBufferConstructor);
+
+ // Set up the constructor property on the ArrayBuffer prototype object.
+ %SetProperty($ArrayBuffer.prototype, "constructor", $ArrayBuffer, DONT_ENUM);
+
+ InstallGetter($ArrayBuffer.prototype, "byteLength", ArrayBufferGetByteLength);
+
+ InstallFunctions($ArrayBuffer.prototype, DONT_ENUM, $Array(
+ "slice", ArrayBufferSlice
+ ));
+
+})();
diff --git a/deps/v8/src/v8globals.h b/deps/v8/src/v8globals.h
index 8874cfb25..4b4d312f9 100644
--- a/deps/v8/src/v8globals.h
+++ b/deps/v8/src/v8globals.h
@@ -296,7 +296,7 @@ enum CallFunctionFlags {
enum InlineCacheHolderFlag {
OWN_MAP, // For fast properties objects.
- DELEGATE_MAP // For slow properties objects (except GlobalObjects).
+ PROTOTYPE_MAP // For slow properties objects (except GlobalObjects).
};
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
index 24ad22d96..d9dc09651 100644
--- a/deps/v8/src/v8natives.js
+++ b/deps/v8/src/v8natives.js
@@ -233,7 +233,6 @@ $Object.prototype.constructor = $Object;
function ObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
- if (IS_SYMBOL(this)) return "[object Symbol]";
return "[object " + %_ClassOf(ToObject(this)) + "]";
}
@@ -257,6 +256,9 @@ function ObjectValueOf() {
// ECMA-262 - 15.2.4.5
function ObjectHasOwnProperty(V) {
if (%IsJSProxy(this)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(V)) return false;
+
var handler = %GetHandler(this);
return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, ToName(V));
}
@@ -279,6 +281,9 @@ function ObjectIsPrototypeOf(V) {
function ObjectPropertyIsEnumerable(V) {
var P = ToName(V);
if (%IsJSProxy(this)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(V)) return false;
+
var desc = GetOwnProperty(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
}
@@ -646,6 +651,9 @@ function CallTrap2(handler, name, defaultTrap, x, y) {
function GetOwnProperty(obj, v) {
var p = ToName(v);
if (%IsJSProxy(obj)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(v)) return void 0;
+
var handler = %GetHandler(obj);
var descriptor = CallTrap1(handler, "getOwnPropertyDescriptor", void 0, p);
if (IS_UNDEFINED(descriptor)) return descriptor;
@@ -686,6 +694,9 @@ function Delete(obj, p, should_throw) {
// Harmony proxies.
function DefineProxyProperty(obj, p, attributes, should_throw) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(p)) return false;
+
var handler = %GetHandler(obj);
var result = CallTrap2(handler, "defineProperty", void 0, p, attributes);
if (!ToBoolean(result)) {
@@ -865,7 +876,7 @@ function DefineArrayProperty(obj, p, desc, should_throw) {
// DefineObjectProperty() to modify its value.
// Step 3 - Special handling for length property.
- if (p == "length") {
+ if (p === "length") {
var length = obj.length;
if (!desc.hasValue()) {
return DefineObjectProperty(obj, "length", desc, should_throw);
@@ -951,6 +962,9 @@ function DefineArrayProperty(obj, p, desc, should_throw) {
// ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies.
function DefineOwnProperty(obj, p, desc, should_throw) {
if (%IsJSProxy(obj)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(p)) return false;
+
var attributes = FromGenericPropertyDescriptor(desc);
return DefineProxyProperty(obj, p, attributes, should_throw);
} else if (IS_ARRAY(obj)) {
@@ -988,16 +1002,20 @@ function ToNameArray(obj, trap, includeSymbols) {
}
var n = ToUint32(obj.length);
var array = new $Array(n);
+ var realLength = 0;
var names = { __proto__: null }; // TODO(rossberg): use sets once ready.
for (var index = 0; index < n; index++) {
var s = ToName(obj[index]);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(s) && !includeSymbols) continue;
if (%HasLocalProperty(names, s)) {
throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
}
array[index] = s;
+ ++realLength;
names[s] = 0;
}
+ array.length = realLength;
return array;
}
@@ -1011,7 +1029,7 @@ function ObjectGetOwnPropertyNames(obj) {
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
- return ToNameArray(names, "getOwnPropertyNames", true);
+ return ToNameArray(names, "getOwnPropertyNames", false);
}
var nameArrays = new InternalArray();
@@ -1037,7 +1055,7 @@ function ObjectGetOwnPropertyNames(obj) {
// Find all the named properties.
// Get the local property names.
- nameArrays.push(%GetLocalPropertyNames(obj));
+ nameArrays.push(%GetLocalPropertyNames(obj, false));
// Get names for named interceptor properties if any.
if ((interceptorInfo & 2) != 0) {
@@ -1057,7 +1075,8 @@ function ObjectGetOwnPropertyNames(obj) {
var propertySet = { __proto__: null };
var j = 0;
for (var i = 0; i < propertyNames.length; ++i) {
- var name = ToName(propertyNames[i]);
+ if (IS_SYMBOL(propertyNames[i])) continue;
+ var name = ToString(propertyNames[i]);
// We need to check for the exact property value since for intrinsic
// properties like toString if(propertySet["toString"]) will always
// succeed.
diff --git a/deps/v8/src/v8utils.h b/deps/v8/src/v8utils.h
index 793d34d9c..b5c8f084e 100644
--- a/deps/v8/src/v8utils.h
+++ b/deps/v8/src/v8utils.h
@@ -111,6 +111,7 @@ int WriteAsCFile(const char* filename, const char* varname,
const char* str, int size, bool verbose = true);
+// ----------------------------------------------------------------------------
// Data structures
template <typename T>
@@ -120,21 +121,24 @@ inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
}
+
+// ----------------------------------------------------------------------------
// Memory
-// Copies data from |src| to |dst|. The data spans MUST not overlap.
+// Copies data from |src| to |dst|. The data spans must not overlap.
template <typename T>
inline void CopyWords(T* dst, T* src, int num_words) {
STATIC_ASSERT(sizeof(T) == kPointerSize);
ASSERT(Min(dst, src) + num_words <= Max(dst, src));
ASSERT(num_words > 0);
- // Use block copying memcpy if the segment we're copying is
+ // Use block copying OS::MemCopy if the segment we're copying is
// enough to justify the extra call/setup overhead.
static const int kBlockCopyLimit = 16;
+ STATIC_ASSERT(kBlockCopyLimit * kPointerSize >= OS::kMinComplexMemCopy);
if (num_words >= kBlockCopyLimit) {
- memcpy(dst, src, num_words * kPointerSize);
+ OS::MemCopy(dst, src, num_words * kPointerSize);
} else {
int remaining = num_words;
do {
@@ -145,6 +149,29 @@ inline void CopyWords(T* dst, T* src, int num_words) {
}
+// Copies data from |src| to |dst|. The data spans must not overlap.
+template <typename T>
+inline void CopyBytes(T* dst, T* src, size_t num_bytes) {
+ STATIC_ASSERT(sizeof(T) == 1);
+ ASSERT(Min(dst, src) + num_bytes <= Max(dst, src));
+ if (num_bytes == 0) return;
+
+ // Use block copying OS::MemCopy if the segment we're copying is
+ // enough to justify the extra call/setup overhead.
+ static const int kBlockCopyLimit = OS::kMinComplexMemCopy;
+
+ if (num_bytes >= static_cast<size_t>(kBlockCopyLimit)) {
+ OS::MemCopy(dst, src, num_bytes);
+ } else {
+ size_t remaining = num_bytes;
+ do {
+ remaining--;
+ *dst++ = *src++;
+ } while (remaining > 0);
+ }
+}
+
+
template <typename T, typename U>
inline void MemsetPointer(T** dest, U* value, int counter) {
#ifdef DEBUG
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 4bb5a499d..64ed98d46 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 17
-#define BUILD_NUMBER 13
+#define BUILD_NUMBER 16
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/deps/v8/src/x64/builtins-x64.cc b/deps/v8/src/x64/builtins-x64.cc
index 0b70c1a0c..2da3de2b9 100644
--- a/deps/v8/src/x64/builtins-x64.cc
+++ b/deps/v8/src/x64/builtins-x64.cc
@@ -220,12 +220,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ movzxbq(rdi, FieldOperand(rax, Map::kInstanceSizeOffset));
__ shl(rdi, Immediate(kPointerSizeLog2));
// rdi: size of new object
- __ AllocateInNewSpace(rdi,
- rbx,
- rdi,
- no_reg,
- &rt_call,
- NO_ALLOCATION_FLAGS);
+ __ Allocate(rdi,
+ rbx,
+ rdi,
+ no_reg,
+ &rt_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields.
// rax: initial map
// rbx: JSObject (not HeapObject tagged - the actual address).
@@ -287,14 +287,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// rbx: JSObject
// rdi: start of next object (will be start of FixedArray)
// rdx: number of elements in properties array
- __ AllocateInNewSpace(FixedArray::kHeaderSize,
- times_pointer_size,
- rdx,
- rdi,
- rax,
- no_reg,
- &undo_allocation,
- RESULT_CONTAINS_TOP);
+ __ Allocate(FixedArray::kHeaderSize,
+ times_pointer_size,
+ rdx,
+ rdi,
+ rax,
+ no_reg,
+ &undo_allocation,
+ RESULT_CONTAINS_TOP);
// Initialize the FixedArray.
// rbx: JSObject
@@ -416,10 +416,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
__ j(above_equal, &exit);
- // Symbols are "objects".
- __ CmpInstanceType(rcx, SYMBOL_TYPE);
- __ j(equal, &exit);
-
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ bind(&use_receiver);
@@ -1216,14 +1212,14 @@ static void AllocateJSArray(MacroAssembler* masm,
// requested elements.
SmiIndex index =
masm->SmiToIndex(kScratchRegister, array_size, kPointerSizeLog2);
- __ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
- index.scale,
- index.reg,
- result,
- elements_array_end,
- scratch,
- gc_required,
- TAG_OBJECT);
+ __ Allocate(JSArray::kSize + FixedArray::kHeaderSize,
+ index.scale,
+ index.reg,
+ result,
+ elements_array_end,
+ scratch,
+ gc_required,
+ TAG_OBJECT);
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc
index 04c3e6837..fffd37f51 100644
--- a/deps/v8/src/x64/code-stubs-x64.cc
+++ b/deps/v8/src/x64/code-stubs-x64.cc
@@ -62,6 +62,17 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
}
+void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { rdx, rcx, rax };
+ descriptor->register_param_count_ = 3;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure);
+}
+
+
void TransitionElementsKindStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -84,7 +95,7 @@ static void InitializeArrayConstructorDescriptor(Isolate* isolate,
// stack param count needs (constructor pointer, and single argument)
descriptor->stack_parameter_count_ = &rax;
descriptor->register_params_ = registers;
- descriptor->extra_expression_stack_count_ = 1;
+ descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
descriptor->deoptimization_handler_ =
FUNCTION_ADDR(ArrayConstructor_StubFailure);
}
@@ -2375,34 +2386,6 @@ void MathPowStub::Generate(MacroAssembler* masm) {
}
-void ArrayLengthStub::Generate(MacroAssembler* masm) {
- Label miss;
- Register receiver;
- if (kind() == Code::KEYED_LOAD_IC) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- __ Cmp(rax, masm->isolate()->factory()->length_string());
- __ j(not_equal, &miss);
- receiver = rdx;
- } else {
- ASSERT(kind() == Code::LOAD_IC);
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
- receiver = rax;
- }
-
- StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss);
- __ bind(&miss);
- StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
-}
-
-
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver;
@@ -2652,7 +2635,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
__ addq(r8, Immediate(Heap::kArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ AllocateInNewSpace(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
+ __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
// rax = address of new object(s) (tagged)
// rcx = argument count (untagged)
@@ -2870,7 +2853,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
__ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict));
// Do the allocation of both objects in one go.
- __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
+ __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
// Get the arguments boilerplate from the current native context.
__ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
@@ -3403,14 +3386,14 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
// Allocate RegExpResult followed by FixedArray with size in rbx.
// JSArray: [Map][empty properties][Elements][Length-smi][index][input]
// Elements: [Map][Length][..elements..]
- __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize,
- times_pointer_size,
- rbx, // In: Number of elements.
- rax, // Out: Start of allocation (tagged).
- rcx, // Out: End of allocation.
- rdx, // Scratch register
- &slowcase,
- TAG_OBJECT);
+ __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize,
+ times_pointer_size,
+ rbx, // In: Number of elements.
+ rax, // Out: Start of allocation (tagged).
+ rcx, // Out: End of allocation.
+ rdx, // Scratch register
+ &slowcase,
+ TAG_OBJECT);
// rax: Start of allocated area, object-tagged.
// rbx: Number of array elements as int32.
// r8: Number of array elements as smi.
@@ -6800,8 +6783,10 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
__ movq(rbx, MemOperand(rbp, parameter_count_offset));
masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
__ pop(rcx);
- __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size,
- extra_expression_stack_count_ * kPointerSize));
+ int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
+ ? kPointerSize
+ : 0;
+ __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset));
__ jmp(rcx); // Return to IC Miss stub, continuation still on stack.
}
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index fa8b44a41..6f32f7cf0 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -347,7 +347,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
// Allocate new backing store.
__ bind(&new_backing_store);
__ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
- __ AllocateInNewSpace(rdi, r14, r11, r15, fail, TAG_OBJECT);
+ __ Allocate(rdi, r14, r11, r15, fail, TAG_OBJECT);
// Set backing store's map
__ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
__ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi);
@@ -435,7 +435,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
// r8 : source FixedDoubleArray
// r9 : number of elements
__ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
- __ AllocateInNewSpace(rdi, r11, r14, r15, &gc_required, TAG_OBJECT);
+ __ Allocate(rdi, r11, r14, r15, &gc_required, TAG_OBJECT);
// r11: destination FixedArray
__ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex);
__ movq(FieldOperand(r11, HeapObject::kMapOffset), rdi);
@@ -769,7 +769,7 @@ void Code::PatchPlatformCodeAge(byte* sequence,
uint32_t young_length;
byte* young_sequence = GetNoCodeAgeSequence(&young_length);
if (age == kNoAge) {
- memcpy(sequence, young_sequence, young_length);
+ CopyBytes(sequence, young_sequence, young_length);
CPU::FlushICache(sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(age, parity);
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index 8ff12df36..322479dec 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -2678,28 +2678,6 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
}
-void FullCodeGenerator::EmitIsSymbol(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(rax, if_false);
- __ CmpObjectType(rax, SYMBOL_TYPE, rbx);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 1);
@@ -4271,6 +4249,10 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
Split(zero, if_true, if_false, fall_through);
+ } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ __ JumpIfSmi(rax, if_false);
+ __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
+ Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
__ j(equal, if_true);
@@ -4302,10 +4284,6 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ CompareRoot(rax, Heap::kNullValueRootIndex);
__ j(equal, if_true);
}
- if (FLAG_harmony_symbols) {
- __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
- __ j(equal, if_true);
- }
__ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
__ j(below, if_false);
__ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc
index b9bd30bb1..817a9d35e 100644
--- a/deps/v8/src/x64/lithium-codegen-x64.cc
+++ b/deps/v8/src/x64/lithium-codegen-x64.cc
@@ -1574,13 +1574,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
-void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
- Register result = ToRegister(instr->result());
- Register array = ToRegister(instr->value());
- __ movq(result, FieldOperand(array, JSArray::kLengthOffset));
-}
-
-
void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->value());
@@ -5129,7 +5122,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
- __ AllocateInNewSpace(size, result, temp, no_reg, deferred->entry(), flags);
+ __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
}
__ bind(deferred->exit());
@@ -5538,6 +5531,11 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
Immediate(1 << Map::kIsUndetectable));
final_branch_condition = zero;
+ } else if (type_name->Equals(heap()->symbol_string())) {
+ __ JumpIfSmi(input, false_label);
+ __ CmpObjectType(input, SYMBOL_TYPE, input);
+ final_branch_condition = equal;
+
} else if (type_name->Equals(heap()->boolean_string())) {
__ CompareRoot(input, Heap::kTrueValueRootIndex);
__ j(equal, true_label);
@@ -5572,13 +5570,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ CompareRoot(input, Heap::kNullValueRootIndex);
__ j(equal, true_label);
}
- if (FLAG_harmony_symbols) {
- __ CmpObjectType(input, SYMBOL_TYPE, input);
- __ j(equal, true_label);
- __ CmpInstanceType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- } else {
- __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
- }
+ __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
__ j(below, false_label);
__ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
__ j(above, false_label);
diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc
index 16248ee17..9a3166ee4 100644
--- a/deps/v8/src/x64/lithium-x64.cc
+++ b/deps/v8/src/x64/lithium-x64.cc
@@ -879,6 +879,35 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LInstruction* instr = current->CompileToLithium(this);
if (instr != NULL) {
+#if DEBUG
+ // Make sure that the lithium instruction has either no fixed register
+ // constraints in temps or the result OR no uses that are only used at
+ // start. If this invariant doesn't hold, the register allocator can decide
+ // to insert a split of a range immediately before the instruction due to an
+ // already allocated register needing to be used for the instruction's fixed
+ // register constraint. In this case, The register allocator won't see an
+ // interference between the split child and the use-at-start (it would if
+ // the it was just a plain use), so it is free to move the split child into
+ // the same register that is used for the use-at-start.
+ // See https://code.google.com/p/chromium/issues/detail?id=201590
+ if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
+ int fixed = 0;
+ int used_at_start = 0;
+ for (UseIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->IsUsedAtStart()) ++used_at_start;
+ }
+ if (instr->Output() != NULL) {
+ if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
+ }
+ for (TempIterator it(instr); !it.Done(); it.Advance()) {
+ LUnallocated* operand = LUnallocated::cast(it.Current());
+ if (operand->HasFixedPolicy()) ++fixed;
+ }
+ ASSERT(fixed == 0 || used_at_start == 0);
+ }
+#endif
+
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -1632,12 +1661,6 @@ LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
}
-LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
- LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LJSArrayLength(array));
-}
-
-
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h
index 9e3e836ed..051f9a469 100644
--- a/deps/v8/src/x64/lithium-x64.h
+++ b/deps/v8/src/x64/lithium-x64.h
@@ -121,7 +121,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
@@ -1109,19 +1108,6 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 0> {
};
-class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LJSArrayLength(LOperand* value) {
- inputs_[0] = value;
- }
-
- LOperand* value() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
- DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
-};
-
-
class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
public:
explicit LFixedArrayBaseLength(LOperand* value) {
@@ -2034,7 +2020,7 @@ class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
};
-class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
+class LTransitionElementsKind: public LTemplateInstruction<0, 1, 2> {
public:
LTransitionElementsKind(LOperand* object,
LOperand* new_map_temp,
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index 9ecf66c5e..6c1c19df3 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -3830,16 +3830,15 @@ void MacroAssembler::Allocate(int object_size,
}
-void MacroAssembler::AllocateInNewSpace(int header_size,
- ScaleFactor element_size,
- Register element_count,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT((flags & SIZE_IN_WORDS) == 0);
- ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -3866,15 +3865,15 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
}
// Calculate new top and bail out if new space is exhausted.
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
// We assume that element_count*element_size + header_size does not
// overflow.
lea(result_end, Operand(element_count, element_size, header_size));
addq(result_end, result);
j(carry, gc_required);
- Operand limit_operand = ExternalOperand(new_space_allocation_limit);
+ Operand limit_operand = ExternalOperand(allocation_limit);
cmpq(result_end, limit_operand);
j(above, gc_required);
@@ -3889,14 +3888,13 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
}
-void MacroAssembler::AllocateInNewSpace(Register object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(Register object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
- ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -3916,14 +3914,14 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
LoadAllocationTopHelper(result, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
if (!object_size.is(result_end)) {
movq(result_end, object_size);
}
addq(result_end, result);
j(carry, gc_required);
- Operand limit_operand = ExternalOperand(new_space_allocation_limit);
+ Operand limit_operand = ExternalOperand(allocation_limit);
cmpq(result_end, limit_operand);
j(above, gc_required);
@@ -3991,14 +3989,14 @@ void MacroAssembler::AllocateTwoByteString(Register result,
}
// Allocate two byte string in new space.
- AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
- times_1,
- scratch1,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(SeqTwoByteString::kHeaderSize,
+ times_1,
+ scratch1,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
@@ -4029,14 +4027,14 @@ void MacroAssembler::AllocateAsciiString(Register result,
}
// Allocate ASCII string in new space.
- AllocateInNewSpace(SeqOneByteString::kHeaderSize,
- times_1,
- scratch1,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ Allocate(SeqOneByteString::kHeaderSize,
+ times_1,
+ scratch1,
+ result,
+ scratch2,
+ scratch3,
+ gc_required,
+ TAG_OBJECT);
// Set the map, length and hash field.
LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h
index df5215991..3381a5b7b 100644
--- a/deps/v8/src/x64/macro-assembler-x64.h
+++ b/deps/v8/src/x64/macro-assembler-x64.h
@@ -1042,21 +1042,21 @@ class MacroAssembler: public Assembler {
Label* gc_required,
AllocationFlags flags);
- void AllocateInNewSpace(int header_size,
- ScaleFactor element_size,
- Register element_count,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
- void AllocateInNewSpace(Register object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(Register object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
// Undo allocation in new space. The object passed and objects allocated after
// it will no longer be allocated. Make sure that no pointers are left to the
diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc
index 69d7a91b2..7e900dbe6 100644
--- a/deps/v8/src/x64/stub-cache-x64.cc
+++ b/deps/v8/src/x64/stub-cache-x64.cc
@@ -716,7 +716,7 @@ void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
// but may be destroyed if store is successful.
void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object,
- int index,
+ LookupResult* lookup,
Handle<Map> transition,
Handle<Name> name,
Register receiver_reg,
@@ -726,16 +726,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Register scratch2,
Label* miss_label,
Label* miss_restore_name) {
- LookupResult lookup(masm->isolate());
- object->Lookup(*name, &lookup);
- if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
- // In sloppy mode, we could just return the value and be done. However, we
- // might be in strict mode, where we have to throw. Since we cannot tell,
- // go into slow case unconditionally.
- __ jmp(miss_label);
- return;
- }
-
// Check that the map of the object hasn't changed.
CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
: REQUIRE_EXACT_MAP;
@@ -750,8 +740,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Check that we are allowed to write this.
if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
JSObject* holder;
- if (lookup.IsFound()) {
- holder = lookup.holder();
+ // holder == object indicates that no property was found.
+ if (lookup->holder() != *object) {
+ holder = lookup->holder();
} else {
// Find the top object.
holder = *object;
@@ -759,8 +750,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject());
}
- CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, miss_restore_name);
+ Register holder_reg = CheckPrototypes(
+ object, receiver_reg, Handle<JSObject>(holder), name_reg,
+ scratch1, scratch2, name, miss_restore_name);
+ // If no property was found, and the holder (the last object in the
+ // prototype chain) is in slow mode, we need to do a negative lookup on the
+ // holder.
+ if (lookup->holder() == *object &&
+ !holder->HasFastProperties() &&
+ !holder->IsJSGlobalProxy() &&
+ !holder->IsJSGlobalObject()) {
+ GenerateDictionaryNegativeLookup(
+ masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
+ }
}
// Stub never generated for non-global objects that require access
@@ -784,6 +786,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
return;
}
+ int index;
if (!transition.is_null()) {
// Update the map of the object.
__ Move(scratch1, transition);
@@ -798,6 +801,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kDontSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
+ index = transition->instance_descriptors()->GetFieldIndex(
+ transition->LastAdded());
+ } else {
+ index = lookup->GetFieldIndex().field_index();
}
// Adjust for the number of properties stored in the object. Even in the
@@ -2174,6 +2181,12 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
// Check that the object is a symbol.
__ CmpObjectType(rdx, SYMBOL_TYPE, rax);
__ j(not_equal, &miss);
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss);
+ CheckPrototypes(
+ Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
+ rax, holder, rbx, rdx, rdi, name, &miss);
break;
case NUMBER_CHECK: {
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index e06cb77c6..a9780f033 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -8376,7 +8376,7 @@ THREADED_TEST(Regress91517) {
// Call the runtime version of GetLocalPropertyNames() on the natively
// created object through JavaScript.
context->Global()->Set(v8_str("obj"), o4);
- CompileRun("var names = %GetLocalPropertyNames(obj);");
+ CompileRun("var names = %GetLocalPropertyNames(obj, true);");
ExpectInt32("names.length", 1006);
ExpectTrue("names.indexOf(\"baz\") >= 0");
@@ -16054,15 +16054,17 @@ THREADED_TEST(TwoByteStringInAsciiCons) {
CHECK(flat_string->IsTwoByteRepresentation());
- // At this point, we should have a Cons string which is flat and ASCII,
- // with a first half that is a two-byte string (although it only contains
- // ASCII characters). This is a valid sequence of steps, and it can happen
- // in real pages.
-
- CHECK(string->IsOneByteRepresentation());
- i::ConsString* cons = i::ConsString::cast(*string);
- CHECK_EQ(0, cons->second()->length());
- CHECK(cons->first()->IsTwoByteRepresentation());
+ // If the cons string has been short-circuited, skip the following checks.
+ if (!string.is_identical_to(flat_string)) {
+ // At this point, we should have a Cons string which is flat and ASCII,
+ // with a first half that is a two-byte string (although it only contains
+ // ASCII characters). This is a valid sequence of steps, and it can happen
+ // in real pages.
+ CHECK(string->IsOneByteRepresentation());
+ i::ConsString* cons = i::ConsString::cast(*string);
+ CHECK_EQ(0, cons->second()->length());
+ CHECK(cons->first()->IsTwoByteRepresentation());
+ }
// Check that some string operations work.
diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc
index 04d7ecb4f..0bf80003f 100644
--- a/deps/v8/test/cctest/test-cpu-profiler.cc
+++ b/deps/v8/test/cctest/test-cpu-profiler.cc
@@ -300,100 +300,102 @@ TEST(DeleteAllCpuProfiles) {
TEST(DeleteCpuProfile) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
v8::Local<v8::String> name1 = v8::String::New("1");
- v8::CpuProfiler::StartProfiling(name1);
- const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
+ cpu_profiler->StartCpuProfiling(name1);
+ const v8::CpuProfile* p1 = cpu_profiler->StopCpuProfiling(name1);
CHECK_NE(NULL, p1);
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
unsigned uid1 = p1->GetUid();
- CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
+ CHECK_EQ(p1, cpu_profiler->FindCpuProfile(uid1));
const_cast<v8::CpuProfile*>(p1)->Delete();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1));
v8::Local<v8::String> name2 = v8::String::New("2");
- v8::CpuProfiler::StartProfiling(name2);
- const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2);
+ cpu_profiler->StartCpuProfiling(name2);
+ const v8::CpuProfile* p2 = cpu_profiler->StopCpuProfiling(name2);
CHECK_NE(NULL, p2);
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
unsigned uid2 = p2->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
- CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+ CHECK_EQ(p2, cpu_profiler->FindCpuProfile(uid2));
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1));
v8::Local<v8::String> name3 = v8::String::New("3");
- v8::CpuProfiler::StartProfiling(name3);
- const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
+ cpu_profiler->StartCpuProfiling(name3);
+ const v8::CpuProfile* p3 = cpu_profiler->StopCpuProfiling(name3);
CHECK_NE(NULL, p3);
- CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(2, cpu_profiler->GetProfileCount());
unsigned uid3 = p3->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
- CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+ CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3));
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1));
const_cast<v8::CpuProfile*>(p2)->Delete();
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
- CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2));
+ CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3));
const_cast<v8::CpuProfile*>(p3)->Delete();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3));
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2));
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1));
}
TEST(DeleteCpuProfileDifferentTokens) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
v8::Local<v8::String> name1 = v8::String::New("1");
- v8::CpuProfiler::StartProfiling(name1);
- const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
+ cpu_profiler->StartCpuProfiling(name1);
+ const v8::CpuProfile* p1 = cpu_profiler->StopCpuProfiling(name1);
CHECK_NE(NULL, p1);
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
unsigned uid1 = p1->GetUid();
- CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
+ CHECK_EQ(p1, cpu_profiler->FindCpuProfile(uid1));
v8::Local<v8::String> token1 = v8::String::New("token1");
- const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1);
+ const v8::CpuProfile* p1_t1 = cpu_profiler->FindCpuProfile(uid1, token1);
CHECK_NE(NULL, p1_t1);
CHECK_NE(p1, p1_t1);
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
const_cast<v8::CpuProfile*>(p1)->Delete();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1));
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1, token1));
const_cast<v8::CpuProfile*>(p1_t1)->Delete();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
v8::Local<v8::String> name2 = v8::String::New("2");
- v8::CpuProfiler::StartProfiling(name2);
+ cpu_profiler->StartCpuProfiling(name2);
v8::Local<v8::String> token2 = v8::String::New("token2");
- const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2);
+ const v8::CpuProfile* p2_t2 = cpu_profiler->StopCpuProfiling(name2, token2);
CHECK_NE(NULL, p2_t2);
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
unsigned uid2 = p2_t2->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
- const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
+ const v8::CpuProfile* p2 = cpu_profiler->FindCpuProfile(uid2);
CHECK_NE(p2_t2, p2);
v8::Local<v8::String> name3 = v8::String::New("3");
- v8::CpuProfiler::StartProfiling(name3);
- const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
+ cpu_profiler->StartCpuProfiling(name3);
+ const v8::CpuProfile* p3 = cpu_profiler->StopCpuProfiling(name3);
CHECK_NE(NULL, p3);
- CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
+ CHECK_EQ(2, cpu_profiler->GetProfileCount());
unsigned uid3 = p3->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
- CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+ CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3));
const_cast<v8::CpuProfile*>(p2_t2)->Delete();
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
- CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2));
+ CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3));
const_cast<v8::CpuProfile*>(p2)->Delete();
- CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
- CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+ CHECK_EQ(1, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2));
+ CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3));
const_cast<v8::CpuProfile*>(p3)->Delete();
- CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
- CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
+ CHECK_EQ(0, cpu_profiler->GetProfileCount());
+ CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3));
}
diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc
index 263ad0277..a536f30b5 100644
--- a/deps/v8/test/cctest/test-heap-profiler.cc
+++ b/deps/v8/test/cctest/test-heap-profiler.cc
@@ -129,6 +129,7 @@ static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
TEST(HeapSnapshot) {
LocalContext env2;
v8::HandleScope scope(env2->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env2->GetIsolate()->GetHeapProfiler();
CompileRun(
"function A2() {}\n"
@@ -138,7 +139,7 @@ TEST(HeapSnapshot) {
"var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
"var c2 = new C2(a2);");
const v8::HeapSnapshot* snapshot_env2 =
- v8::HeapProfiler::TakeSnapshot(v8_str("env2"));
+ heap_profiler->TakeHeapSnapshot(v8_str("env2"));
const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
// Verify, that JS global object of env2 has '..2' properties.
@@ -163,6 +164,7 @@ TEST(HeapSnapshot) {
TEST(HeapSnapshotObjectSizes) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
// -a-> X1 --a
// x -b-> X2 <-|
@@ -172,7 +174,7 @@ TEST(HeapSnapshotObjectSizes) {
"dummy = new X();\n"
"(function() { x.a.a = x.b; })();");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
+ heap_profiler->TakeHeapSnapshot(v8_str("sizes"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* x =
GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
@@ -194,12 +196,13 @@ TEST(HeapSnapshotObjectSizes) {
TEST(BoundFunctionInSnapshot) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function myFunction(a, b) { this.a = a; this.b = b; }\n"
"function AAAAA() {}\n"
"boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
+ heap_profiler->TakeHeapSnapshot(v8_str("sizes"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* f =
GetProperty(global, v8::HeapGraphEdge::kProperty, "boundFunction");
@@ -231,12 +234,13 @@ TEST(BoundFunctionInSnapshot) {
TEST(HeapSnapshotEntryChildren) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function A() { }\n"
"a = new A;");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("children"));
+ heap_profiler->TakeHeapSnapshot(v8_str("children"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) {
const v8::HeapGraphEdge* prop = global->GetChild(i);
@@ -255,6 +259,7 @@ TEST(HeapSnapshotEntryChildren) {
TEST(HeapSnapshotCodeObjects) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function lazy(x) { return x - 1; }\n"
@@ -262,7 +267,7 @@ TEST(HeapSnapshotCodeObjects) {
"var anonymous = (function() { return function() { return 0; } })();\n"
"compiled(1)");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("code"));
+ heap_profiler->TakeHeapSnapshot(v8_str("code"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* compiled =
@@ -320,11 +325,12 @@ TEST(HeapSnapshotCodeObjects) {
TEST(HeapSnapshotHeapNumbers) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"a = 1; // a is Smi\n"
"b = 2.5; // b is HeapNumber");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("numbers"));
+ heap_profiler->TakeHeapSnapshot(v8_str("numbers"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a"));
const v8::HeapGraphNode* b =
@@ -336,6 +342,7 @@ TEST(HeapSnapshotHeapNumbers) {
TEST(HeapSnapshotSlicedString) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"parent_string = \"123456789.123456789.123456789.123456789.123456789."
"123456789.123456789.123456789.123456789.123456789."
@@ -343,7 +350,7 @@ TEST(HeapSnapshotSlicedString) {
"123456789.123456789.123456789.123456789.123456789.\";"
"child_string = parent_string.slice(100);");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("strings"));
+ heap_profiler->TakeHeapSnapshot(v8_str("strings"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* parent_string =
GetProperty(global, v8::HeapGraphEdge::kProperty, "parent_string");
@@ -357,7 +364,8 @@ TEST(HeapSnapshotSlicedString) {
}
TEST(HeapSnapshotInternalReferences) {
- v8::HandleScope scope(v8::Isolate::GetCurrent());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
global_template->SetInternalFieldCount(2);
LocalContext env(NULL, global_template);
@@ -367,8 +375,9 @@ TEST(HeapSnapshotInternalReferences) {
v8::Local<v8::Object> obj = v8::Object::New();
global->SetInternalField(0, v8_num(17));
global->SetInternalField(1, obj);
+ v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("internals"));
+ heap_profiler->TakeHeapSnapshot(v8_str("internals"));
const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
// The first reference will not present, because it's a Smi.
CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"));
@@ -388,6 +397,7 @@ TEST(HeapSnapshotInternalReferences) {
TEST(HeapSnapshotAddressReuse) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function A() {}\n"
@@ -395,7 +405,7 @@ TEST(HeapSnapshotAddressReuse) {
"for (var i = 0; i < 10000; ++i)\n"
" a[i] = new A();\n");
const v8::HeapSnapshot* snapshot1 =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot1"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot1"));
v8::SnapshotObjectId maxId1 = snapshot1->GetMaxSnapshotJSObjectId();
CompileRun(
@@ -404,7 +414,7 @@ TEST(HeapSnapshotAddressReuse) {
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
const v8::HeapSnapshot* snapshot2 =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot2"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot2"));
const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
const v8::HeapGraphNode* array_node =
@@ -426,6 +436,7 @@ TEST(HeapSnapshotAddressReuse) {
TEST(HeapEntryIdsAndArrayShift) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function AnObject() {\n"
@@ -436,7 +447,7 @@ TEST(HeapEntryIdsAndArrayShift) {
"for (var i = 0; i < 10; ++i)\n"
" a.push(new AnObject());\n");
const v8::HeapSnapshot* snapshot1 =
- v8::HeapProfiler::TakeSnapshot(v8_str("s1"));
+ heap_profiler->TakeHeapSnapshot(v8_str("s1"));
CompileRun(
"for (var i = 0; i < 1; ++i)\n"
@@ -445,7 +456,7 @@ TEST(HeapEntryIdsAndArrayShift) {
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
const v8::HeapSnapshot* snapshot2 =
- v8::HeapProfiler::TakeSnapshot(v8_str("s2"));
+ heap_profiler->TakeHeapSnapshot(v8_str("s2"));
const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
@@ -472,6 +483,7 @@ TEST(HeapEntryIdsAndArrayShift) {
TEST(HeapEntryIdsAndGC) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function A() {}\n"
@@ -481,12 +493,12 @@ TEST(HeapEntryIdsAndGC) {
v8::Local<v8::String> s1_str = v8_str("s1");
v8::Local<v8::String> s2_str = v8_str("s2");
const v8::HeapSnapshot* snapshot1 =
- v8::HeapProfiler::TakeSnapshot(s1_str);
+ heap_profiler->TakeHeapSnapshot(s1_str);
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
const v8::HeapSnapshot* snapshot2 =
- v8::HeapProfiler::TakeSnapshot(s2_str);
+ heap_profiler->TakeHeapSnapshot(s2_str);
CHECK_GT(snapshot1->GetMaxSnapshotJSObjectId(), 7000);
CHECK(snapshot1->GetMaxSnapshotJSObjectId() <=
@@ -534,8 +546,9 @@ TEST(HeapEntryIdsAndGC) {
TEST(HeapSnapshotRootPreservedAfterSorting) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("s"));
+ heap_profiler->TakeHeapSnapshot(v8_str("s"));
const v8::HeapGraphNode* root1 = snapshot->GetRoot();
const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
snapshot))->GetSortedEntriesList();
@@ -592,6 +605,7 @@ class AsciiResource: public v8::String::ExternalAsciiStringResource {
TEST(HeapSnapshotJSONSerialization) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
#define STRING_LITERAL_FOR_TEST \
"\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
@@ -601,7 +615,7 @@ TEST(HeapSnapshotJSONSerialization) {
"var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
"var b = new B(a);");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("json"));
+ heap_profiler->TakeHeapSnapshot(v8_str("json"));
TestJSONStream stream;
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
CHECK_GT(stream.size(), 0);
@@ -694,8 +708,9 @@ TEST(HeapSnapshotJSONSerialization) {
TEST(HeapSnapshotJSONSerializationAborting) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("abort"));
+ heap_profiler->TakeHeapSnapshot(v8_str("abort"));
TestJSONStream stream(5);
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
CHECK_GT(stream.size(), 0);
@@ -761,10 +776,10 @@ class TestStatsStream : public v8::OutputStream {
} // namespace
static TestStatsStream GetHeapStatsUpdate(
+ v8::HeapProfiler* heap_profiler,
v8::SnapshotObjectId* object_id = NULL) {
TestStatsStream stream;
- v8::SnapshotObjectId last_seen_id =
- v8::HeapProfiler::PushHeapObjectsStats(&stream);
+ v8::SnapshotObjectId last_seen_id = heap_profiler->GetHeapStats(&stream);
if (object_id)
*object_id = last_seen_id;
CHECK_EQ(1, stream.eos_signaled());
@@ -775,8 +790,9 @@ static TestStatsStream GetHeapStatsUpdate(
TEST(HeapSnapshotObjectsStats) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- v8::HeapProfiler::StartHeapObjectsTracking();
+ heap_profiler->StartTrackingHeapObjects();
// We have to call GC 6 times. In other case the garbage will be
// the reason of flakiness.
for (int i = 0; i < 6; ++i) {
@@ -786,7 +802,8 @@ TEST(HeapSnapshotObjectsStats) {
v8::SnapshotObjectId initial_id;
{
// Single chunk of data expected in update. Initial data.
- TestStatsStream stats_update = GetHeapStatsUpdate(&initial_id);
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler,
+ &initial_id);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
CHECK_LT(0, stats_update.entries_size());
@@ -795,7 +812,7 @@ TEST(HeapSnapshotObjectsStats) {
// No data expected in update because nothing has happened.
v8::SnapshotObjectId same_id;
- CHECK_EQ(0, GetHeapStatsUpdate(&same_id).updates_written());
+ CHECK_EQ(0, GetHeapStatsUpdate(heap_profiler, &same_id).updates_written());
CHECK_EQ_SNAPSHOT_OBJECT_ID(initial_id, same_id);
{
@@ -804,7 +821,8 @@ TEST(HeapSnapshotObjectsStats) {
v8_str("string1");
{
// Single chunk of data with one new entry expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate(&additional_string_id);
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler,
+ &additional_string_id);
CHECK_LT(same_id, additional_string_id);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
@@ -815,7 +833,7 @@ TEST(HeapSnapshotObjectsStats) {
// No data expected in update because nothing happened.
v8::SnapshotObjectId last_id;
- CHECK_EQ(0, GetHeapStatsUpdate(&last_id).updates_written());
+ CHECK_EQ(0, GetHeapStatsUpdate(heap_profiler, &last_id).updates_written());
CHECK_EQ_SNAPSHOT_OBJECT_ID(additional_string_id, last_id);
{
@@ -830,7 +848,7 @@ TEST(HeapSnapshotObjectsStats) {
{
// Single chunk of data with three new entries expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate();
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
CHECK_LT(0, entries_size = stats_update.entries_size());
@@ -841,7 +859,7 @@ TEST(HeapSnapshotObjectsStats) {
{
// Single chunk of data with two left entries expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate();
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
CHECK_GT(entries_size, stats_update.entries_size());
@@ -853,7 +871,7 @@ TEST(HeapSnapshotObjectsStats) {
{
// Single chunk of data with 0 left entries expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate();
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
CHECK_EQ(0, stats_update.entries_size());
@@ -864,7 +882,7 @@ TEST(HeapSnapshotObjectsStats) {
}
{
// Single chunk of data with 0 left entries expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate();
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
CHECK_EQ(0, stats_update.entries_size());
@@ -881,7 +899,7 @@ TEST(HeapSnapshotObjectsStats) {
uint32_t entries_size;
{
// Single chunk of data with 2 entries expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate();
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler);
CHECK_EQ(1, stats_update.intervals_count());
CHECK_EQ(1, stats_update.updates_written());
CHECK_LT(0, entries_size = stats_update.entries_size());
@@ -895,7 +913,7 @@ TEST(HeapSnapshotObjectsStats) {
{
// Single chunk of data with 1 entry expected in update.
- TestStatsStream stats_update = GetHeapStatsUpdate();
+ TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler);
CHECK_EQ(1, stats_update.intervals_count());
// The first interval was changed because old buffer was collected.
// The second interval was changed because new buffer was allocated.
@@ -905,7 +923,7 @@ TEST(HeapSnapshotObjectsStats) {
CHECK_EQ(8, stats_update.first_interval_index());
}
- v8::HeapProfiler::StopHeapObjectsTracking();
+ heap_profiler->StopTrackingHeapObjects();
}
@@ -928,9 +946,10 @@ static void CheckChildrenIds(const v8::HeapSnapshot* snapshot,
TEST(HeapSnapshotGetNodeById) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("id"));
+ heap_profiler->TakeHeapSnapshot(v8_str("id"));
const v8::HeapGraphNode* root = snapshot->GetRoot();
CheckChildrenIds(snapshot, root, 0, 3);
// Check a big id, which should not exist yet.
@@ -941,9 +960,10 @@ TEST(HeapSnapshotGetNodeById) {
TEST(HeapSnapshotGetSnapshotObjectId) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("globalObject = {};\n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("get_snapshot_object_id"));
+ heap_profiler->TakeHeapSnapshot(v8_str("get_snapshot_object_id"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* global_object =
GetProperty(global, v8::HeapGraphEdge::kProperty, "globalObject");
@@ -954,8 +974,7 @@ TEST(HeapSnapshotGetSnapshotObjectId) {
CHECK(!globalObjectHandle.IsEmpty());
CHECK(globalObjectHandle->IsObject());
- v8::SnapshotObjectId id =
- v8::HeapProfiler::GetSnapshotObjectId(globalObjectHandle);
+ v8::SnapshotObjectId id = heap_profiler->GetObjectId(globalObjectHandle);
CHECK_NE(static_cast<int>(v8::HeapProfiler::kUnknownObjectId),
id);
CHECK_EQ(static_cast<int>(id), global_object->GetId());
@@ -965,9 +984,10 @@ TEST(HeapSnapshotGetSnapshotObjectId) {
TEST(HeapSnapshotUnknownSnapshotObjectId) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("globalObject = {};\n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("unknown_object_id"));
+ heap_profiler->TakeHeapSnapshot(v8_str("unknown_object_id"));
const v8::HeapGraphNode* node =
snapshot->GetNodeById(v8::HeapProfiler::kUnknownObjectId);
CHECK_EQ(NULL, node);
@@ -999,23 +1019,22 @@ TEST(TakeHeapSnapshotAborting) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount();
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+ const int snapshots_count = heap_profiler->GetSnapshotCount();
TestActivityControl aborting_control(1);
const v8::HeapSnapshot* no_snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("abort"),
- v8::HeapSnapshot::kFull,
+ heap_profiler->TakeHeapSnapshot(v8_str("abort"),
&aborting_control);
CHECK_EQ(NULL, no_snapshot);
- CHECK_EQ(snapshots_count, v8::HeapProfiler::GetSnapshotsCount());
+ CHECK_EQ(snapshots_count, heap_profiler->GetSnapshotCount());
CHECK_GT(aborting_control.total(), aborting_control.done());
TestActivityControl control(-1); // Don't abort.
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("full"),
- v8::HeapSnapshot::kFull,
+ heap_profiler->TakeHeapSnapshot(v8_str("full"),
&control);
CHECK_NE(NULL, snapshot);
- CHECK_EQ(snapshots_count + 1, v8::HeapProfiler::GetSnapshotsCount());
+ CHECK_EQ(snapshots_count + 1, heap_profiler->GetSnapshotCount());
CHECK_EQ(control.total(), control.done());
CHECK_GT(control.total(), 0);
}
@@ -1109,10 +1128,11 @@ TEST(HeapSnapshotRetainedObjectInfo) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
+ v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
- v8::HeapProfiler::DefineWrapperClass(
+ heap_profiler->SetWrapperClassInfoProvider(
1, TestRetainedObjectInfo::WrapperInfoCallback);
- v8::HeapProfiler::DefineWrapperClass(
+ heap_profiler->SetWrapperClassInfoProvider(
2, TestRetainedObjectInfo::WrapperInfoCallback);
v8::Persistent<v8::String> p_AAA =
v8::Persistent<v8::String>::New(isolate, v8_str("AAA"));
@@ -1125,7 +1145,7 @@ TEST(HeapSnapshotRetainedObjectInfo) {
p_CCC.SetWrapperClassId(isolate, 2);
CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("retained"));
+ heap_profiler->TakeHeapSnapshot(v8_str("retained"));
CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) {
@@ -1205,12 +1225,13 @@ GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL;
TEST(HeapSnapshotImplicitReferences) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
GraphWithImplicitRefs graph(&env);
v8::V8::AddGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue);
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs"));
+ heap_profiler->TakeHeapSnapshot(v8_str("implicit_refs"));
const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot);
const v8::HeapGraphNode* obj0 = GetProperty(
@@ -1237,58 +1258,60 @@ TEST(HeapSnapshotImplicitReferences) {
TEST(DeleteAllHeapSnapshots) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
-
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- v8::HeapProfiler::DeleteAllSnapshots();
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
- CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
- v8::HeapProfiler::DeleteAllSnapshots();
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
- CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("2")));
- CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
- v8::HeapProfiler::DeleteAllSnapshots();
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
+ heap_profiler->DeleteAllHeapSnapshots();
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
+ CHECK_NE(NULL, heap_profiler->TakeHeapSnapshot(v8_str("1")));
+ CHECK_EQ(1, heap_profiler->GetSnapshotCount());
+ heap_profiler->DeleteAllHeapSnapshots();
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
+ CHECK_NE(NULL, heap_profiler->TakeHeapSnapshot(v8_str("1")));
+ CHECK_NE(NULL, heap_profiler->TakeHeapSnapshot(v8_str("2")));
+ CHECK_EQ(2, heap_profiler->GetSnapshotCount());
+ heap_profiler->DeleteAllHeapSnapshots();
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
}
TEST(DeleteHeapSnapshot) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
const v8::HeapSnapshot* s1 =
- v8::HeapProfiler::TakeSnapshot(v8_str("1"));
+ heap_profiler->TakeHeapSnapshot(v8_str("1"));
CHECK_NE(NULL, s1);
- CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+ CHECK_EQ(1, heap_profiler->GetSnapshotCount());
unsigned uid1 = s1->GetUid();
- CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1));
+ CHECK_EQ(s1, heap_profiler->FindHeapSnapshot(uid1));
const_cast<v8::HeapSnapshot*>(s1)->Delete();
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1));
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
+ CHECK_EQ(NULL, heap_profiler->FindHeapSnapshot(uid1));
const v8::HeapSnapshot* s2 =
- v8::HeapProfiler::TakeSnapshot(v8_str("2"));
+ heap_profiler->TakeHeapSnapshot(v8_str("2"));
CHECK_NE(NULL, s2);
- CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+ CHECK_EQ(1, heap_profiler->GetSnapshotCount());
unsigned uid2 = s2->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
- CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2));
+ CHECK_EQ(s2, heap_profiler->FindHeapSnapshot(uid2));
const v8::HeapSnapshot* s3 =
- v8::HeapProfiler::TakeSnapshot(v8_str("3"));
+ heap_profiler->TakeHeapSnapshot(v8_str("3"));
CHECK_NE(NULL, s3);
- CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
+ CHECK_EQ(2, heap_profiler->GetSnapshotCount());
unsigned uid3 = s3->GetUid();
CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
- CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
+ CHECK_EQ(s3, heap_profiler->FindHeapSnapshot(uid3));
const_cast<v8::HeapSnapshot*>(s2)->Delete();
- CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2));
- CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
+ CHECK_EQ(1, heap_profiler->GetSnapshotCount());
+ CHECK_EQ(NULL, heap_profiler->FindHeapSnapshot(uid2));
+ CHECK_EQ(s3, heap_profiler->FindHeapSnapshot(uid3));
const_cast<v8::HeapSnapshot*>(s3)->Delete();
- CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
- CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3));
+ CHECK_EQ(0, heap_profiler->GetSnapshotCount());
+ CHECK_EQ(NULL, heap_profiler->FindHeapSnapshot(uid3));
}
@@ -1302,13 +1325,13 @@ class NameResolver : public v8::HeapProfiler::ObjectNameResolver {
TEST(GlobalObjectName) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("document = { URL:\"abcdefgh\" };");
NameResolver name_resolver;
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("document"),
- v8::HeapSnapshot::kFull,
+ heap_profiler->TakeHeapSnapshot(v8_str("document"),
NULL,
&name_resolver);
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
@@ -1322,13 +1345,14 @@ TEST(GlobalObjectName) {
TEST(NoHandleLeaks) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("document = { URL:\"abcdefgh\" };");
v8::Handle<v8::String> name(v8_str("leakz"));
i::Isolate* isolate = i::Isolate::Current();
int count_before = i::HandleScope::NumberOfHandles(isolate);
- v8::HeapProfiler::TakeSnapshot(name);
+ heap_profiler->TakeHeapSnapshot(name);
int count_after = i::HandleScope::NumberOfHandles(isolate);
CHECK_EQ(count_before, count_after);
}
@@ -1337,8 +1361,9 @@ TEST(NoHandleLeaks) {
TEST(NodesIteration) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("iteration"));
+ heap_profiler->TakeHeapSnapshot(v8_str("iteration"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
// Verify that we can find this object by iteration.
@@ -1355,10 +1380,11 @@ TEST(NodesIteration) {
TEST(GetHeapValue) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("value"));
+ heap_profiler->TakeHeapSnapshot(v8_str("value"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK(global->GetHeapValue()->IsObject());
v8::Local<v8::Object> js_global =
@@ -1385,13 +1411,14 @@ TEST(GetHeapValue) {
TEST(GetHeapValueForDeletedObject) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
// It is impossible to delete a global property, so we are about to delete a
// property of the "a" object. Also, the "p" object can't be an empty one
// because the empty object is static and isn't actually deleted.
CompileRun("a = { p: { r: {} } };");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* obj = GetProperty(
global, v8::HeapGraphEdge::kProperty, "a");
@@ -1467,6 +1494,7 @@ TEST(GetConstructorName) {
TEST(FastCaseGetter) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("var obj1 = {};\n"
"obj1.__defineGetter__('propWithGetter', function Y() {\n"
@@ -1476,7 +1504,7 @@ TEST(FastCaseGetter) {
" return this.value_ = value;\n"
"});\n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter"));
+ heap_profiler->TakeHeapSnapshot(v8_str("fastCaseGetter"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
@@ -1494,12 +1522,13 @@ TEST(FastCaseGetter) {
TEST(HiddenPropertiesFastCase) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function C(x) { this.a = this; this.b = x; }\n"
"c = new C(2012);\n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("HiddenPropertiesFastCase1"));
+ heap_profiler->TakeHeapSnapshot(v8_str("HiddenPropertiesFastCase1"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* c =
GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
@@ -1512,7 +1541,7 @@ TEST(HiddenPropertiesFastCase) {
CHECK(!cHandle.IsEmpty() && cHandle->IsObject());
cHandle->ToObject()->SetHiddenValue(v8_str("key"), v8_str("val"));
- snapshot = v8::HeapProfiler::TakeSnapshot(
+ snapshot = heap_profiler->TakeHeapSnapshot(
v8_str("HiddenPropertiesFastCase2"));
global = GetGlobalObject(snapshot);
c = GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
@@ -1532,8 +1561,10 @@ bool HasWeakEdge(const v8::HeapGraphNode* node) {
bool HasWeakGlobalHandle() {
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("weaks"));
+ heap_profiler->TakeHeapSnapshot(v8_str("weaks"));
const v8::HeapGraphNode* gc_roots = GetNode(
snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
CHECK_NE(NULL, gc_roots);
@@ -1568,9 +1599,10 @@ TEST(WeakGlobalHandle) {
TEST(WeakNativeContextRefs) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("weaks"));
+ heap_profiler->TakeHeapSnapshot(v8_str("weaks"));
const v8::HeapGraphNode* gc_roots = GetNode(
snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
CHECK_NE(NULL, gc_roots);
@@ -1587,11 +1619,12 @@ TEST(WeakNativeContextRefs) {
TEST(SfiAndJsFunctionWeakRefs) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"fun = (function (x) { return function () { return x + 1; } })(1);");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("fun"));
+ heap_profiler->TakeHeapSnapshot(v8_str("fun"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
const v8::HeapGraphNode* fun =
@@ -1607,11 +1640,12 @@ TEST(SfiAndJsFunctionWeakRefs) {
TEST(NoDebugObjectInSnapshot) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
v8::internal::Isolate::Current()->debug()->Load();
CompileRun("foo = {};");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
const v8::HeapGraphNode* root = snapshot->GetRoot();
int globals_count = 0;
for (int i = 0; i < root->GetChildrenCount(); ++i) {
@@ -1667,10 +1701,11 @@ TEST(PersistentHandleCount) {
TEST(AllStrongGcRootsHaveNames) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("foo = {};");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
const v8::HeapGraphNode* gc_roots = GetNode(
snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
CHECK_NE(NULL, gc_roots);
@@ -1689,9 +1724,10 @@ TEST(AllStrongGcRootsHaveNames) {
TEST(NoRefsToNonEssentialEntries) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("global_object = {};\n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* global_object =
GetProperty(global, v8::HeapGraphEdge::kProperty, "global_object");
@@ -1708,9 +1744,10 @@ TEST(NoRefsToNonEssentialEntries) {
TEST(MapHasDescriptorsAndTransitions) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("obj = { a: 10 };\n");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* global_object =
GetProperty(global, v8::HeapGraphEdge::kProperty, "obj");
@@ -1729,8 +1766,9 @@ TEST(MapHasDescriptorsAndTransitions) {
TEST(ManyLocalsInSharedContext) {
- v8::HandleScope scope;
LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
int num_objects = 6000;
CompileRun(
"var n = 6000;"
@@ -1747,7 +1785,7 @@ TEST(ManyLocalsInSharedContext) {
"result.push('})()');"
"var ok = eval(result.join('\\n'));");
const v8::HeapSnapshot* snapshot =
- v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global);
const v8::HeapGraphNode* ok_object =
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
index a710385bf..d0bec935d 100644
--- a/deps/v8/test/cctest/test-heap.cc
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -1240,6 +1240,7 @@ TEST(TestCodeFlushingIncrementalAbort) {
// code flushing candidate.
SimulateIncrementalMarking();
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Enable the debugger and add a breakpoint while incremental marking
// is running so that incremental marking aborts and code flushing is
// disabled.
@@ -1247,6 +1248,7 @@ TEST(TestCodeFlushingIncrementalAbort) {
Handle<Object> breakpoint_object(Smi::FromInt(0), isolate);
isolate->debug()->SetBreakPoint(function, breakpoint_object, &position);
isolate->debug()->ClearAllBreakPoints();
+#endif // ENABLE_DEBUGGER_SUPPORT
// Force optimization now that code flushing is disabled.
{ v8::HandleScope scope(env->GetIsolate());
@@ -3010,8 +3012,10 @@ TEST(Regress173458) {
// explicitly enqueued.
SimulateIncrementalMarking();
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Now enable the debugger which in turn will disable code flushing.
CHECK(isolate->debug()->Load());
+#endif // ENABLE_DEBUGGER_SUPPORT
// This cycle will bust the heap and subsequent cycles will go ballistic.
heap->CollectAllGarbage(Heap::kNoGCFlags);
diff --git a/deps/v8/test/cctest/test-profile-generator.cc b/deps/v8/test/cctest/test-profile-generator.cc
index 864229ee3..56b1788a8 100644
--- a/deps/v8/test/cctest/test-profile-generator.cc
+++ b/deps/v8/test/cctest/test-profile-generator.cc
@@ -830,20 +830,22 @@ v8::Handle<v8::FunctionTemplate> ProfilerExtension::GetNativeFunction(
v8::Handle<v8::Value> ProfilerExtension::StartProfiling(
const v8::Arguments& args) {
+ v8::CpuProfiler* cpu_profiler = args.GetIsolate()->GetCpuProfiler();
if (args.Length() > 0)
- v8::CpuProfiler::StartProfiling(args[0].As<v8::String>());
+ cpu_profiler->StartCpuProfiling(args[0].As<v8::String>());
else
- v8::CpuProfiler::StartProfiling(v8::String::New(""));
+ cpu_profiler->StartCpuProfiling(v8::String::New(""));
return v8::Undefined();
}
v8::Handle<v8::Value> ProfilerExtension::StopProfiling(
const v8::Arguments& args) {
+ v8::CpuProfiler* cpu_profiler = args.GetIsolate()->GetCpuProfiler();
if (args.Length() > 0)
- v8::CpuProfiler::StopProfiling(args[0].As<v8::String>());
+ cpu_profiler->StopCpuProfiling(args[0].As<v8::String>());
else
- v8::CpuProfiler::StopProfiling(v8::String::New(""));
+ cpu_profiler->StopCpuProfiling(v8::String::New(""));
return v8::Undefined();
}
diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc
index f240e9314..9aebdb18f 100644
--- a/deps/v8/test/cctest/test-strings.cc
+++ b/deps/v8/test/cctest/test-strings.cc
@@ -1082,7 +1082,9 @@ TEST(SliceFromCons) {
CHECK(parent->IsFlat());
CHECK(slice->IsSlicedString());
CHECK_EQ(SlicedString::cast(*slice)->parent(),
- ConsString::cast(*parent)->first());
+ // Parent could have been short-circuited.
+ parent->IsConsString() ? ConsString::cast(*parent)->first()
+ : *parent);
CHECK(SlicedString::cast(*slice)->parent()->IsSeqString());
CHECK(slice->IsFlat());
}
diff --git a/deps/v8/test/message/overwritten-builtins.out b/deps/v8/test/message/overwritten-builtins.out
index 77d72c144..db31bbf08 100644
--- a/deps/v8/test/message/overwritten-builtins.out
+++ b/deps/v8/test/message/overwritten-builtins.out
@@ -30,3 +30,4 @@ undefined.x
^
TypeError: Cannot read property 'x' of undefined
at *%(basename)s:31:10
+
diff --git a/deps/v8/test/mjsunit/array-non-smi-length.js b/deps/v8/test/mjsunit/array-non-smi-length.js
new file mode 100644
index 000000000..23a25ee79
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-non-smi-length.js
@@ -0,0 +1,46 @@
+// Copyright 2013 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
+
+function TestNonSmiArrayLength() {
+ function f(a) {
+ return a.length+1;
+ }
+
+ var a = [];
+ a.length = 0xFFFF;
+ assertSame(0x10000, f(a));
+ assertSame(0x10000, f(a));
+
+ %OptimizeFunctionOnNextCall(f);
+ a.length = 0xFFFFFFFF;
+ assertSame(0x100000000, f(a));
+}
+
+TestNonSmiArrayLength();
+
diff --git a/deps/v8/test/mjsunit/array-shift.js b/deps/v8/test/mjsunit/array-shift.js
index 3601cbbb8..ad742e12e 100644
--- a/deps/v8/test/mjsunit/array-shift.js
+++ b/deps/v8/test/mjsunit/array-shift.js
@@ -106,3 +106,17 @@
assertEquals(array[7], array_proto[7]);
assertFalse(array.hasOwnProperty(7));
})();
+
+// Check that non-enumerable elements are treated appropriately
+(function() {
+ var array = [1, 2, 3];
+ Object.defineProperty(array, '1', {enumerable: false});
+ assertEquals(1, array.shift());
+ assertEquals([2, 3], array);
+
+ array = [1,,3];
+ array.__proto__[1] = 2;
+ Object.defineProperty(array.__proto__, '1', {enumerable: false});
+ assertEquals(1, array.shift());
+ assertEquals([2, 3], array);
+})();
diff --git a/deps/v8/test/mjsunit/array-splice.js b/deps/v8/test/mjsunit/array-splice.js
index 0e307b5d3..be2b1064e 100644
--- a/deps/v8/test/mjsunit/array-splice.js
+++ b/deps/v8/test/mjsunit/array-splice.js
@@ -285,8 +285,8 @@
assertFalse(array.hasOwnProperty(15), "array.hasOwnProperty(15)");
assertFalse(array.hasOwnProperty(31), "array.hasOwnProperty(31)");
assertFalse(array.hasOwnProperty(63), "array.hasOwnProperty(63)");
- assertFalse(array.hasOwnProperty(2 << 32 - 1),
- "array.hasOwnProperty(2 << 31 - 1)");
+ assertFalse(array.hasOwnProperty(Math.pow(2, 32) - 2),
+ "array.hasOwnProperty(Math.pow(2, 32) - 2)");
}
})();
@@ -333,8 +333,8 @@
assertFalse(array.hasOwnProperty(15), "array.hasOwnProperty(15)");
assertFalse(array.hasOwnProperty(31), "array.hasOwnProperty(31)");
assertFalse(array.hasOwnProperty(63), "array.hasOwnProperty(63)");
- assertFalse(array.hasOwnProperty(2 << 32 - 1),
- "array.hasOwnProperty(2 << 31 - 1)");
+ assertFalse(array.hasOwnProperty(Math.pow(2, 32) - 2),
+ "array.hasOwnProperty(Math.pow(2, 32) - 2)");
}
})();
@@ -357,7 +357,7 @@
(function() {
for (var i = 0; i < 7; i++) {
try {
- new Array((1 << 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
+ new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
throw 'Should have thrown RangeError';
} catch (e) {
assertTrue(e instanceof RangeError);
diff --git a/deps/v8/test/mjsunit/array-unshift.js b/deps/v8/test/mjsunit/array-unshift.js
index c4cc95cbb..0eb299a0c 100644
--- a/deps/v8/test/mjsunit/array-unshift.js
+++ b/deps/v8/test/mjsunit/array-unshift.js
@@ -194,7 +194,7 @@
(function() {
for (var i = 0; i < 7; i++) {
try {
- new Array((1 << 32) - 3).unshift(1, 2, 3, 4, 5);
+ new Array(Math.pow(2, 32) - 3).unshift(1, 2, 3, 4, 5);
throw 'Should have thrown RangeError';
} catch (e) {
assertTrue(e instanceof RangeError);
@@ -213,3 +213,18 @@
assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a);
}
})();
+
+// Check that non-enumerable elements are treated appropriately
+(function() {
+ var array = [2, 3];
+ Object.defineProperty(array, '1', {enumerable: false});
+ array.unshift(1)
+ assertEquals([1, 2, 3], array);
+
+ array = [2];
+ array.length = 2;
+ array.__proto__[1] = 3;
+ Object.defineProperty(array.__proto__, '1', {enumerable: false});
+ array.unshift(1);
+ assertEquals([1, 2, 3], array);
+})();
diff --git a/deps/v8/test/mjsunit/compiler/rotate.js b/deps/v8/test/mjsunit/compiler/rotate.js
index 1db1fb329..14fe9da3e 100644
--- a/deps/v8/test/mjsunit/compiler/rotate.js
+++ b/deps/v8/test/mjsunit/compiler/rotate.js
@@ -221,3 +221,4 @@ for (var i = 0; i <= 100; i++) {
%OptimizeFunctionOnNextCall(ROR4);
assertEquals(1 << ((i % 32)), ROR4(1, i));
}
+
diff --git a/deps/v8/test/mjsunit/debug-evaluate-locals.js b/deps/v8/test/mjsunit/debug-evaluate-locals.js
index 61b6dd9bb..a68162d9b 100644
--- a/deps/v8/test/mjsunit/debug-evaluate-locals.js
+++ b/deps/v8/test/mjsunit/debug-evaluate-locals.js
@@ -36,19 +36,20 @@ exception = false;
function h() {
var a = 1;
var b = 2;
+ var eval = 5; // Overriding eval should not break anything.
debugger; // Breakpoint.
}
function checkFrame0(frame) {
// Frame 0 (h) has normal variables a and b.
var count = frame.localCount();
- assertEquals(2, count);
+ assertEquals(3, count);
for (var i = 0; i < count; ++i) {
var name = frame.localName(i);
var value = frame.localValue(i).value();
if (name == 'a') {
assertEquals(1, value);
- } else {
+ } else if (name !='eval') {
assertEquals('b', name);
assertEquals(2, value);
}
@@ -115,16 +116,21 @@ function listener(event, exec_state, event_data, data) {
// Evaluating a and b on frames 0, 1 and 2 produces 1, 2, 3, 4, 5 and 6.
assertEquals(1, exec_state.frame(0).evaluate('a').value());
assertEquals(2, exec_state.frame(0).evaluate('b').value());
+ assertEquals(5, exec_state.frame(0).evaluate('eval').value());
assertEquals(3, exec_state.frame(1).evaluate('a').value());
assertEquals(4, exec_state.frame(1).evaluate('b').value());
+ assertEquals("function",
+ typeof exec_state.frame(1).evaluate('eval').value());
assertEquals(5, exec_state.frame(2).evaluate('a').value());
assertEquals(6, exec_state.frame(2).evaluate('b').value());
-
+ assertEquals("function",
+ typeof exec_state.frame(2).evaluate('eval').value());
// Indicate that all was processed.
listenerComplete = true;
}
} catch (e) {
exception = e
+ print("Caught something. " + e + " " + e.stack);
};
};
@@ -133,6 +139,6 @@ Debug.setListener(listener);
f();
-// Make sure that the debug event listener vas invoked.
-assertTrue(listenerComplete);
+// Make sure that the debug event listener was invoked.
assertFalse(exception, "exception in listener")
+assertTrue(listenerComplete);
diff --git a/deps/v8/test/mjsunit/debug-liveedit-compile-error.js b/deps/v8/test/mjsunit/debug-liveedit-compile-error.js
index 99ac0314a..2fd6aedab 100644
--- a/deps/v8/test/mjsunit/debug-liveedit-compile-error.js
+++ b/deps/v8/test/mjsunit/debug-liveedit-compile-error.js
@@ -56,3 +56,5 @@ assertEquals("Unexpected token )",
caught_exception.details.syntaxErrorMessage);
assertEquals(2, caught_exception.details.position.start.line);
+
+
diff --git a/deps/v8/test/mjsunit/elements-kind.js b/deps/v8/test/mjsunit/elements-kind.js
index d95255605..0e8e209ef 100644
--- a/deps/v8/test/mjsunit/elements-kind.js
+++ b/deps/v8/test/mjsunit/elements-kind.js
@@ -28,9 +28,10 @@
// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
// Flags: --notrack_allocation_sites
-// Limit the number of stress runs to reduce polymorphism it defeats some of
-// they assumptions made about how elements transitions work because transition
-// stubs end up going generic. Flags: --stress-runs=2
+// Limit the number of stress runs to reduce polymorphism it defeats some of the
+// assumptions made about how elements transitions work because transition stubs
+// end up going generic.
+// Flags: --stress-runs=2
// Test element kind of objects.
// Since --smi-only-arrays affects builtins, its default setting at compile
diff --git a/deps/v8/test/mjsunit/error-accessors.js b/deps/v8/test/mjsunit/error-accessors.js
index cdaf080a3..958105024 100644
--- a/deps/v8/test/mjsunit/error-accessors.js
+++ b/deps/v8/test/mjsunit/error-accessors.js
@@ -51,3 +51,4 @@ assertEquals("x is not defined",
o.message = "another message";
assertEquals("another message", o.message);
assertEquals("x is not defined", error2.message);
+
diff --git a/deps/v8/test/mjsunit/harmony/generators-parsing.js b/deps/v8/test/mjsunit/harmony/generators-parsing.js
new file mode 100644
index 000000000..0e5494df1
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/generators-parsing.js
@@ -0,0 +1,100 @@
+// Copyright 2013 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: --harmony-generators
+
+// Test basic generator syntax.
+
+// Yield statements.
+function* g() { yield 3; yield 4; }
+
+// Yield expressions.
+function* g() { (yield 3) + (yield 4); }
+
+// You can have a generator in strict mode.
+function* g() { "use strict"; yield 3; yield 4; }
+
+// Generator expression.
+(function* () { yield 3; });
+
+// Named generator expression.
+(function* g() { yield 3; });
+
+// A generator without a yield is specified as causing an early error. This
+// behavior is currently unimplemented. See
+// https://bugs.ecmascript.org/show_bug.cgi?id=1283.
+function* g() { }
+
+// A YieldExpression in the RHS of a YieldExpression is currently specified as
+// causing an early error. This behavior is currently unimplemented. See
+// https://bugs.ecmascript.org/show_bug.cgi?id=1283.
+function* g() { yield yield 1; }
+function* g() { yield 3 + (yield 4); }
+
+// Generator definitions with a name of "yield" are not specifically ruled out
+// by the spec, as the `yield' name is outside the generator itself. However,
+// in strict-mode, "yield" is an invalid identifier.
+function* yield() { (yield 3) + (yield 4); }
+assertThrows("function* yield() { \"use strict\"; (yield 3) + (yield 4); }",
+ SyntaxError);
+
+// In classic mode, yield is a normal identifier, outside of generators.
+function yield(yield) { yield: yield (yield + yield (0)); }
+
+// Yield is always valid as a key in an object literal.
+({ yield: 1 });
+function* g() { yield ({ yield: 1 }) }
+function* g() { yield ({ get yield() { return 1; }}) }
+
+// Checks that yield is a valid label in classic mode, but not valid in a strict
+// mode or in generators.
+function f() { yield: 1 }
+assertThrows("function f() { \"use strict\"; yield: 1 }", SyntaxError)
+assertThrows("function f*() { yield: 1 }", SyntaxError)
+
+// Yield is only a keyword in the body of the generator, not in nested
+// functions.
+function* g() { function f() { yield (yield + yield (0)); } }
+
+// Yield needs a RHS.
+assertThrows("function* g() { yield; }", SyntaxError);
+
+// Yield in a generator is not an identifier.
+assertThrows("function* g() { yield = 10; }", SyntaxError);
+
+// Yield binds very loosely, so this parses as "yield (3 + yield 4)", which is
+// invalid.
+assertThrows("function* g() { yield 3 + yield 4; }", SyntaxError);
+
+// Yield is still a future-reserved-word in strict mode
+assertThrows("function f() { \"use strict\"; var yield = 13; }", SyntaxError);
+
+// The name of the NFE is let-bound in G, so is invalid.
+assertThrows("function* g() { yield (function yield() {}); }", SyntaxError);
+
+// In generators, yield is invalid as a formal argument name.
+assertThrows("function* g(yield) { yield (10); }", SyntaxError);
diff --git a/deps/v8/test/mjsunit/harmony/object-observe.js b/deps/v8/test/mjsunit/harmony/object-observe.js
index 584d9e82d..263154a40 100644
--- a/deps/v8/test/mjsunit/harmony/object-observe.js
+++ b/deps/v8/test/mjsunit/harmony/object-observe.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-observation --harmony-proxies --harmony-collections
-// Flags: --allow-natives-syntax
+// Flags: --harmony-symbols --allow-natives-syntax
var allObservers = [];
function reset() {
@@ -448,6 +448,29 @@ observer.assertCallbackRecords([
]);
+// Observing symbol properties (not).
+print("*****")
+reset();
+var obj = {}
+var symbol = Symbol("secret");
+Object.observe(obj, observer.callback);
+obj[symbol] = 3;
+delete obj[symbol];
+Object.defineProperty(obj, symbol, {get: function() {}, configurable: true});
+Object.defineProperty(obj, symbol, {value: 6});
+Object.defineProperty(obj, symbol, {writable: false});
+delete obj[symbol];
+Object.defineProperty(obj, symbol, {value: 7});
+++obj[symbol];
+obj[symbol]++;
+obj[symbol] *= 3;
+delete obj[symbol];
+obj.__defineSetter__(symbol, function() {});
+obj.__defineGetter__(symbol, function() {});
+Object.deliverChangeRecords(observer.callback);
+observer.assertNotCalled();
+
+
// Test all kinds of objects generically.
function TestObserveConfigurable(obj, prop) {
reset();
diff --git a/deps/v8/test/mjsunit/harmony/proxies-symbols.js b/deps/v8/test/mjsunit/harmony/proxies-symbols.js
new file mode 100644
index 000000000..8920e3996
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/proxies-symbols.js
@@ -0,0 +1,106 @@
+// Copyright 2013 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: --harmony-proxies --harmony-symbols
+
+
+// Helper.
+
+function TestWithProxies(test, x, y, z) {
+ test(Proxy.create, x, y, z)
+ test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z)
+}
+
+
+// No symbols should leak to proxy traps.
+
+function TestNoSymbolsToTrap(handler) {
+ TestWithProxies(TestNoSymbolsToTrap2, handler)
+}
+
+function TestNoSymbolsToTrap2(create, handler) {
+ var p = create(handler)
+ var o = Object.create(p)
+ var symbol = Symbol("secret")
+
+ assertFalse(symbol in p)
+ assertFalse(symbol in o)
+ assertEquals(undefined, p[symbol])
+ assertEquals(undefined, o[symbol])
+ assertEquals(47, p[symbol] = 47)
+ assertEquals(47, o[symbol] = 47)
+ assertFalse(delete p[symbol])
+ assertTrue(delete o[symbol])
+ assertTrue(delete o[symbol])
+ assertFalse({}.hasOwnProperty.call(p, symbol))
+ assertFalse({}.hasOwnProperty.call(o, symbol))
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(p, symbol))
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(o, symbol))
+}
+
+
+TestNoSymbolsToTrap({
+ has: assertUnreachable,
+ hasOwn: assertUnreachable,
+ get: assertUnreachable,
+ set: assertUnreachable,
+ delete: assertUnreachable,
+ getPropertyDescriptor: assertUnreachable,
+ getOwnPropertyDescriptor: assertUnreachable,
+ defineProperty: assertUnreachable
+})
+
+
+// All symbols returned from proxy traps should be filtered.
+
+function TestNoSymbolsFromTrap(handler) {
+ TestWithProxies(TestNoSymbolsFromTrap2, handler)
+}
+
+function TestNoSymbolsFromTrap2(create, handler) {
+ var p = create(handler)
+ var o = Object.create(p)
+
+ assertEquals(0, Object.keys(p).length)
+ assertEquals(0, Object.keys(o).length)
+ assertEquals(0, Object.getOwnPropertyNames(p).length)
+ assertEquals(0, Object.getOwnPropertyNames(o).length)
+ for (var n in p) assertUnreachable()
+ for (var n in o) assertUnreachable()
+}
+
+
+function MakeSymbolArray() {
+ return [Symbol(), Symbol("a")]
+}
+
+TestNoSymbolsFromTrap({
+ enumerate: MakeSymbolArray,
+ keys: MakeSymbolArray,
+ getPropertyNames: MakeSymbolArray,
+ getOwnPropertyNames: MakeSymbolArray
+})
diff --git a/deps/v8/test/mjsunit/harmony/symbols.js b/deps/v8/test/mjsunit/harmony/symbols.js
index cdc63628a..a3f6e5720 100644
--- a/deps/v8/test/mjsunit/harmony/symbols.js
+++ b/deps/v8/test/mjsunit/harmony/symbols.js
@@ -34,20 +34,22 @@ var symbols = []
function TestNew() {
function IndirectSymbol() { return new Symbol }
function indirect() { return new IndirectSymbol() }
- for (var i = 0; i < 10; ++i) {
- symbols.push(new Symbol)
- symbols.push(new Symbol())
- symbols.push(Symbol())
- symbols.push(indirect())
- }
- %OptimizeFunctionOnNextCall(indirect)
- indirect() // Call once before GC throws away type feedback.
- gc() // Promote existing symbols and then allocate some more.
- for (var i = 0; i < 10; ++i) {
- symbols.push(new Symbol)
- symbols.push(new Symbol())
- symbols.push(Symbol())
- symbols.push(indirect())
+ for (var i = 0; i < 2; ++i) {
+ for (var j = 0; j < 5; ++j) {
+ symbols.push(Symbol())
+ symbols.push(Symbol(undefined))
+ symbols.push(Symbol("66"))
+ symbols.push(Symbol(66))
+ symbols.push(Symbol(Symbol()))
+ symbols.push((new Symbol).valueOf())
+ symbols.push((new Symbol()).valueOf())
+ symbols.push((new Symbol(Symbol())).valueOf())
+ symbols.push(Object(Symbol()).valueOf())
+ symbols.push((indirect()).valueOf())
+ }
+ %OptimizeFunctionOnNextCall(indirect)
+ indirect() // Call once before GC throws away type feedback.
+ gc() // Promote existing symbols and then allocate some more.
}
}
TestNew()
@@ -55,23 +57,91 @@ TestNew()
function TestType() {
for (var i in symbols) {
- assertTrue(%_IsSymbol(symbols[i]))
- assertEquals("object", typeof symbols[i])
- assertTrue(typeof symbols[i] === "object")
- assertEquals("[object Symbol]", Object.prototype.toString.call(symbols[i]))
+ assertEquals("symbol", typeof symbols[i])
+ assertTrue(typeof symbols[i] === "symbol")
+ assertEquals(null, %_ClassOf(symbols[i]))
+ assertEquals("Symbol", %_ClassOf(new Symbol(symbols[i])))
+ assertEquals("Symbol", %_ClassOf(Object(symbols[i])))
}
}
TestType()
+function TestPrototype() {
+ assertSame(Object.prototype, Symbol.prototype.__proto__)
+ assertSame(Symbol.prototype, Symbol().__proto__)
+ assertSame(Symbol.prototype, Symbol(Symbol()).__proto__)
+ assertSame(Symbol.prototype, (new Symbol).__proto__)
+ assertSame(Symbol.prototype, (new Symbol()).__proto__)
+ assertSame(Symbol.prototype, (new Symbol(Symbol())).__proto__)
+ assertSame(Symbol.prototype, Object(Symbol()).__proto__)
+ for (var i in symbols) {
+ assertSame(Symbol.prototype, symbols[i].__proto__)
+ }
+}
+TestPrototype()
+
+
+function TestName() {
+ for (var i in symbols) {
+ var name = symbols[i].name
+ assertTrue(name === undefined || name === "66")
+ }
+}
+TestName()
+
+
+function TestToString() {
+ for (var i in symbols) {
+ assertThrows(function() { String(symbols[i]) }, TypeError)
+ assertThrows(function() { symbols[i] + "" }, TypeError)
+ assertThrows(function() { symbols[i].toString() }, TypeError)
+ assertThrows(function() { (new Symbol(symbols[i])).toString() }, TypeError)
+ assertThrows(function() { Object(symbols[i]).toString() }, TypeError)
+ assertEquals("[object Symbol]", Object.prototype.toString.call(symbols[i]))
+ }
+}
+TestToString()
+
+
+function TestToBoolean() {
+ for (var i in symbols) {
+ assertTrue(Boolean(symbols[i]).valueOf())
+ assertFalse(!symbols[i])
+ assertTrue(!!symbols[i])
+ assertTrue(symbols[i] && true)
+ assertFalse(!symbols[i] && false)
+ assertTrue(!symbols[i] || true)
+ assertEquals(1, symbols[i] ? 1 : 2)
+ assertEquals(2, !symbols[i] ? 1 : 2)
+ if (!symbols[i]) assertUnreachable();
+ if (symbols[i]) {} else assertUnreachable();
+ }
+}
+TestToBoolean()
+
+
+function TestToNumber() {
+ for (var i in symbols) {
+ assertSame(NaN, Number(symbols[i]).valueOf())
+ assertSame(NaN, symbols[i] + 0)
+ }
+}
+TestToNumber()
+
+
function TestEquality() {
- // Every symbol should equal itself.
+ // Every symbol should equal itself, and non-strictly equal its wrapper.
for (var i in symbols) {
assertSame(symbols[i], symbols[i])
assertEquals(symbols[i], symbols[i])
assertTrue(Object.is(symbols[i], symbols[i]))
assertTrue(symbols[i] === symbols[i])
assertTrue(symbols[i] == symbols[i])
+ assertFalse(symbols[i] === new Symbol(symbols[i]))
+ assertFalse(new Symbol(symbols[i]) === symbols[i])
+ assertTrue(symbols[i] == new Symbol(symbols[i]))
+ assertTrue(new Symbol(symbols[i]) == symbols[i])
}
// All symbols should be distinct.
@@ -82,14 +152,25 @@ function TestEquality() {
assertFalse(symbols[i] == symbols[j])
}
}
+
+ // Symbols should not be equal to any other value (and the test terminates).
+ var values = [347, 1.275, NaN, "string", null, undefined, {}, function() {}]
+ for (var i in symbols) {
+ for (var j in values) {
+ assertFalse(symbols[i] === values[j])
+ assertFalse(values[j] === symbols[i])
+ assertFalse(symbols[i] == values[j])
+ assertFalse(values[j] == symbols[i])
+ }
+ }
}
TestEquality()
function TestGet() {
for (var i in symbols) {
- assertEquals("[object Symbol]", symbols[i].toString())
- assertEquals(undefined, symbols[i].valueOf)
+ assertThrows(function() { symbols[i].toString() }, TypeError)
+ assertEquals(symbols[i], symbols[i].valueOf())
assertEquals(undefined, symbols[i].a)
assertEquals(undefined, symbols[i]["a" + "b"])
assertEquals(undefined, symbols[i]["" + "1"])
@@ -102,7 +183,9 @@ TestGet()
function TestSet() {
for (var i in symbols) {
symbols[i].toString = 0
- assertEquals("[object Symbol]", symbols[i].toString())
+ assertThrows(function() { symbols[i].toString() }, TypeError)
+ symbols[i].valueOf = 0
+ assertEquals(symbols[i], symbols[i].valueOf())
symbols[i].a = 0
assertEquals(undefined, symbols[i].a)
symbols[i]["a" + "b"] = 0
@@ -145,9 +228,12 @@ TestCollections()
function TestKeySet(obj) {
+ assertTrue(%HasFastProperties(obj))
// Set the even symbols via assignment.
for (var i = 0; i < symbols.length; i += 2) {
obj[symbols[i]] = i
+ // Object should remain in fast mode until too many properties were added.
+ assertTrue(%HasFastProperties(obj) || i >= 30)
}
}
@@ -179,7 +265,7 @@ function TestKeyHas() {
function TestKeyEnum(obj) {
for (var name in obj) {
- assertFalse(%_IsSymbol(name))
+ assertEquals("string", typeof name)
}
}
@@ -188,21 +274,9 @@ function TestKeyNames(obj) {
assertEquals(0, Object.keys(obj).length)
var names = Object.getOwnPropertyNames(obj)
- assertTrue(symbols.length <= names.length)
- // TODO(rossberg): once we have iterators, the following would be:
- // var expected = new Set(symbols)
- var expected = new Set
- for (var i = 0; i < symbols.length; ++i) expected.add(symbols[i])
- for (var i = 0; i < names.length; ++i) {
- var name = names[i]
- var asString = String(name)
- if (asString !== name) {
- assertEquals("[object Symbol]", asString)
- assertTrue(expected.has(name))
- expected.delete(name)
- }
+ for (var i in names) {
+ assertEquals("string", typeof names[i])
}
- assertEquals(0, expected.size)
}
@@ -242,3 +316,19 @@ for (var i in objs) {
TestKeyDescriptor(obj)
TestKeyDelete(obj)
}
+
+
+function TestCachedKeyAfterScavenge() {
+ gc();
+ // Keyed property lookup are cached. Hereby we assume that the keys are
+ // tenured, so that we only have to clear the cache between mark compacts,
+ // but not between scavenges. This must also apply for symbol keys.
+ var key = Symbol("key");
+ var a = {};
+ a[key] = "abc";
+
+ for (var i = 0; i < 1000000; i++) {
+ a[key] += "a"; // Allocations cause a scavenge.
+ }
+}
+TestCachedKeyAfterScavenge();
diff --git a/deps/v8/test/mjsunit/harmony/typedarrays.js b/deps/v8/test/mjsunit/harmony/typedarrays.js
new file mode 100644
index 000000000..9b01ba60e
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/typedarrays.js
@@ -0,0 +1,136 @@
+// Copyright 2013 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: --harmony-typed-arrays
+
+function TestByteLength(param, expectedByteLength) {
+ var ab = new __ArrayBuffer(param);
+ assertSame(expectedByteLength, ab.byteLength);
+}
+
+function TestArrayBufferCreation() {
+ TestByteLength(1, 1);
+ TestByteLength(256, 256);
+ TestByteLength(-10, 0);
+ TestByteLength(2.567, 2);
+ TestByteLength(-2.567, 0);
+
+ TestByteLength("abc", 0);
+
+ TestByteLength(0, 0);
+
+ assertThrows(function() {
+ var ab1 = new __ArrayBuffer(0xFFFFFFFFFFFF)
+ }, RangeError);
+
+ var ab = new __ArrayBuffer();
+ assertSame(0, ab.byteLength);
+}
+
+TestArrayBufferCreation();
+
+function TestByteLengthNotWritable() {
+ var ab = new __ArrayBuffer(1024);
+ assertSame(1024, ab.byteLength);
+
+ assertThrows(function() { "use strict"; ab.byteLength = 42; }, TypeError);
+}
+
+TestByteLengthNotWritable();
+
+function TestSlice(expectedResultLen, initialLen, start, end) {
+ var ab = new __ArrayBuffer(initialLen);
+ var slice = ab.slice(start, end);
+ assertSame(expectedResultLen, slice.byteLength);
+}
+
+function TestArrayBufferSlice() {
+ var ab = new __ArrayBuffer(1024);
+ var ab1 = ab.slice(512, 1024);
+ assertSame(512, ab1.byteLength);
+
+ TestSlice(512, 1024, 512, 1024);
+ TestSlice(512, 1024, 512);
+
+ TestSlice(0, 0, 1, 20);
+ TestSlice(100, 100, 0, 100);
+ TestSlice(100, 100, 0, 1000);
+ TestSlice(0, 100, 5, 1);
+
+ TestSlice(1, 100, -11, -10);
+ TestSlice(9, 100, -10, 99);
+ TestSlice(0, 100, -10, 80);
+ TestSlice(10, 100, 80, -10);
+
+ TestSlice(10, 100, 90, "100");
+ TestSlice(10, 100, "90", "100");
+
+ TestSlice(0, 100, 90, "abc");
+ TestSlice(10, 100, "abc", 10);
+
+ TestSlice(10, 100, 0.96, 10.96);
+ TestSlice(10, 100, 0.96, 10.01);
+ TestSlice(10, 100, 0.01, 10.01);
+ TestSlice(10, 100, 0.01, 10.96);
+
+
+ TestSlice(10, 100, 90);
+ TestSlice(10, 100, -10);
+}
+
+TestArrayBufferSlice();
+
+// Test property attribute [[Enumerable]]
+function TestEnumerable(func) {
+ function props(x) {
+ var array = [];
+ for (var p in x) array.push(p);
+ return array.sort();
+ }
+ assertArrayEquals([], props(func));
+ assertArrayEquals([], props(func.prototype));
+ assertArrayEquals([], props(new func()));
+}
+TestEnumerable(__ArrayBuffer);
+
+
+// Test arbitrary properties on ArrayBuffer
+function TestArbitrary(m) {
+ function TestProperty(map, property, value) {
+ map[property] = value;
+ assertEquals(value, map[property]);
+ }
+ for (var i = 0; i < 20; i++) {
+ TestProperty(m, i, 'val' + i);
+ TestProperty(m, 'foo' + i, 'bar' + i);
+ }
+}
+TestArbitrary(new __ArrayBuffer(256));
+
+
+// Test direct constructor call
+assertTrue(__ArrayBuffer() instanceof __ArrayBuffer);
diff --git a/deps/v8/test/mjsunit/json.js b/deps/v8/test/mjsunit/json.js
index 79826dbef..c72c15368 100644
--- a/deps/v8/test/mjsunit/json.js
+++ b/deps/v8/test/mjsunit/json.js
@@ -225,23 +225,28 @@ TestInvalid('"Garbage""After string"');
// Stringify
-assertEquals("true", JSON.stringify(true));
-assertEquals("false", JSON.stringify(false));
-assertEquals("null", JSON.stringify(null));
-assertEquals("false", JSON.stringify({toJSON: function () { return false; }}));
-assertEquals("4", JSON.stringify(4));
-assertEquals('"foo"', JSON.stringify("foo"));
-assertEquals("null", JSON.stringify(Infinity));
-assertEquals("null", JSON.stringify(-Infinity));
-assertEquals("null", JSON.stringify(NaN));
-assertEquals("4", JSON.stringify(new Number(4)));
-assertEquals('"bar"', JSON.stringify(new String("bar")));
-
-assertEquals('"foo\\u0000bar"', JSON.stringify("foo\0bar"));
-assertEquals('"f\\"o\'o\\\\b\\ba\\fr\\nb\\ra\\tz"',
- JSON.stringify("f\"o\'o\\b\ba\fr\nb\ra\tz"));
-
-assertEquals("[1,2,3]", JSON.stringify([1, 2, 3]));
+function TestStringify(expected, input) {
+ assertEquals(expected, JSON.stringify(input));
+ assertEquals(expected, JSON.stringify(input, null, 0));
+}
+
+TestStringify("true", true);
+TestStringify("false", false);
+TestStringify("null", null);
+TestStringify("false", {toJSON: function () { return false; }});
+TestStringify("4", 4);
+TestStringify('"foo"', "foo");
+TestStringify("null", Infinity);
+TestStringify("null", -Infinity);
+TestStringify("null", NaN);
+TestStringify("4", new Number(4));
+TestStringify('"bar"', new String("bar"));
+
+TestStringify('"foo\\u0000bar"', "foo\0bar");
+TestStringify('"f\\"o\'o\\\\b\\ba\\fr\\nb\\ra\\tz"',
+ "f\"o\'o\\b\ba\fr\nb\ra\tz");
+
+TestStringify("[1,2,3]", [1, 2, 3]);
assertEquals("[\n 1,\n 2,\n 3\n]", JSON.stringify([1, 2, 3], null, 1));
assertEquals("[\n 1,\n 2,\n 3\n]", JSON.stringify([1, 2, 3], null, 2));
assertEquals("[\n 1,\n 2,\n 3\n]",
@@ -256,33 +261,38 @@ assertEquals("[1,2,[3,[4],5],6,7]",
JSON.stringify([1, 2, [3, [4], 5], 6, 7], null));
assertEquals("[2,4,[6,[8],10],12,14]",
JSON.stringify([1, 2, [3, [4], 5], 6, 7], DoubleNumbers));
-assertEquals('["a","ab","abc"]', JSON.stringify(["a","ab","abc"]));
-assertEquals('{"a":1,"c":true}',
- JSON.stringify({ a : 1,
- b : function() { 1 },
- c : true,
- d : function() { 2 } }));
-assertEquals('[1,null,true,null]',
- JSON.stringify([1, function() { 1 }, true, function() { 2 }]));
-assertEquals('"toJSON 123"',
- JSON.stringify({ toJSON : function() { return 'toJSON 123'; } }));
-assertEquals('{"a":321}',
- JSON.stringify({ a : { toJSON : function() { return 321; } } }));
+TestStringify('["a","ab","abc"]', ["a","ab","abc"]);
+TestStringify('{"a":1,"c":true}', { a : 1,
+ b : function() { 1 },
+ c : true,
+ d : function() { 2 } });
+TestStringify('[1,null,true,null]',
+ [1, function() { 1 }, true, function() { 2 }]);
+TestStringify('"toJSON 123"',
+ { toJSON : function() { return 'toJSON 123'; } });
+TestStringify('{"a":321}',
+ { a : { toJSON : function() { return 321; } } });
var counter = 0;
assertEquals('{"getter":123}',
JSON.stringify({ get getter() { counter++; return 123; } }));
assertEquals(1, counter);
-assertEquals('{"a":"abc","b":"\u1234bc"}',
- JSON.stringify({ a : "abc", b : "\u1234bc" }));
+assertEquals('{"getter":123}',
+ JSON.stringify({ get getter() { counter++; return 123; } },
+ null,
+ 0));
+assertEquals(2, counter);
+
+TestStringify('{"a":"abc","b":"\u1234bc"}',
+ { a : "abc", b : "\u1234bc" });
var a = { a : 1, b : 2 };
delete a.a;
-assertEquals('{"b":2}', JSON.stringify(a));
+TestStringify('{"b":2}', a);
var b = {};
b.__proto__ = { toJSON : function() { return 321;} };
-assertEquals("321", JSON.stringify(b));
+TestStringify("321", b);
var array = [""];
var expected = '""';
@@ -291,18 +301,19 @@ for (var i = 0; i < 10000; i++) {
expected = '"",' + expected;
}
expected = '[' + expected + ']';
-assertEquals(expected, JSON.stringify(array));
+TestStringify(expected, array);
var circular = [1, 2, 3];
circular[2] = circular;
assertThrows(function () { JSON.stringify(circular); }, TypeError);
+assertThrows(function () { JSON.stringify(circular, null, 0); }, TypeError);
var singleton = [];
var multiOccurrence = [singleton, singleton, singleton];
-assertEquals("[[],[],[]]", JSON.stringify(multiOccurrence));
+TestStringify("[[],[],[]]", multiOccurrence);
-assertEquals('{"x":5,"y":6}', JSON.stringify({x:5,y:6}));
+TestStringify('{"x":5,"y":6}', {x:5,y:6});
assertEquals('{"x":5}', JSON.stringify({x:5,y:6}, ['x']));
assertEquals('{\n "a": "b",\n "c": "d"\n}',
JSON.stringify({a:"b",c:"d"}, null, 1));
@@ -312,7 +323,7 @@ assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x']));
var checker = {};
var array = [checker];
checker.toJSON = function(key) { return 1 + key; };
-assertEquals('["10"]', JSON.stringify(array));
+TestStringify('["10"]', array);
// The gap is capped at ten characters if specified as string.
assertEquals('{\n "a": "b",\n "c": "d"\n}',
@@ -329,12 +340,11 @@ assertEquals('{"x":"42"}', JSON.stringify({x: String}, newx));
assertEquals('{"x":42}', JSON.stringify({x: Number}, newx));
assertEquals('{"x":true}', JSON.stringify({x: Boolean}, newx));
-assertEquals(undefined, JSON.stringify(undefined));
-assertEquals(undefined, JSON.stringify(function () { }));
+TestStringify(undefined, undefined);
+TestStringify(undefined, function () { });
// Arrays with missing, undefined or function elements have those elements
// replaced by null.
-assertEquals("[null,null,null]",
- JSON.stringify([undefined,,function(){}]));
+TestStringify("[null,null,null]", [undefined,,function(){}]);
// Objects with undefined or function properties (including replaced properties)
// have those properties ignored.
@@ -415,16 +425,15 @@ var re = /Is callable/;
var reJSON = /Is callable/;
reJSON.toJSON = function() { return "has toJSON"; };
-assertEquals(
- '[37,null,1,"foo","37","true",null,"has toJSON",{},"has toJSON"]',
- JSON.stringify([num37, numFoo, numTrue,
- strFoo, str37, strTrue,
- func, funcJSON, re, reJSON]));
+TestStringify('[37,null,1,"foo","37","true",null,"has toJSON",{},"has toJSON"]',
+ [num37, numFoo, numTrue,
+ strFoo, str37, strTrue,
+ func, funcJSON, re, reJSON]);
var oddball = Object(42);
oddball.__proto__ = { __proto__: null, toString: function() { return true; } };
-assertEquals('1', JSON.stringify(oddball));
+TestStringify('1', oddball);
var getCount = 0;
var callCount = 0;
@@ -433,10 +442,10 @@ var counter = { get toJSON() { getCount++;
return 42; }; } };
// RegExps are not callable, so they are stringified as objects.
-assertEquals('{}', JSON.stringify(/regexp/));
-assertEquals('42', JSON.stringify(counter));
-assertEquals(1, getCount);
-assertEquals(1, callCount);
+TestStringify('{}', /regexp/);
+TestStringify('42', counter);
+assertEquals(2, getCount);
+assertEquals(2, callCount);
var oddball2 = Object(42);
var oddball3 = Object("foo");
@@ -445,13 +454,13 @@ oddball3.__proto__ = { __proto__: null,
valueOf: function() { return true; } };
oddball2.__proto__ = { __proto__: null,
toJSON: function () { return oddball3; } }
-assertEquals('"true"', JSON.stringify(oddball2));
+TestStringify('"true"', oddball2);
var falseNum = Object("37");
falseNum.__proto__ = Number.prototype;
falseNum.toString = function() { return 42; };
-assertEquals('"42"', JSON.stringify(falseNum));
+TestStringify('"42"', falseNum);
// Parse an object value as __proto__.
var o1 = JSON.parse('{"__proto__":[]}');
@@ -472,4 +481,4 @@ assertTrue(o2.hasOwnProperty("__proto__"));
assertTrue(Object.prototype.isPrototypeOf(o2));
var json = '{"stuff before slash\\\\stuff after slash":"whatever"}';
-assertEquals(json, JSON.stringify(JSON.parse(json)));
+TestStringify(json, JSON.parse(json));
diff --git a/deps/v8/test/mjsunit/json2.js b/deps/v8/test/mjsunit/json2.js
index 4c0b8f58c..cf20b909b 100644
--- a/deps/v8/test/mjsunit/json2.js
+++ b/deps/v8/test/mjsunit/json2.js
@@ -25,13 +25,19 @@
// (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
+// Flags: --allow-natives-syntax --expose-externalize-string
// Test JSON.stringify on the global object.
var a = 12345;
assertTrue(JSON.stringify(this).indexOf('"a":12345') > 0);
+assertTrue(JSON.stringify(this, null, 0).indexOf('"a":12345') > 0);
// Test JSON.stringify of array in dictionary mode.
+function TestStringify(expected, input) {
+ assertEquals(expected, JSON.stringify(input));
+ assertEquals(expected, JSON.stringify(input, null, 0));
+}
+
var array_1 = [];
var array_2 = [];
array_1[100000] = 1;
@@ -42,25 +48,25 @@ for (var i = 0; i < 100000; i++) {
}
expected_1 = '[' + nulls + '1]';
expected_2 = '[' + nulls + 'null]';
-assertEquals(expected_1, JSON.stringify(array_1));
-assertEquals(expected_2, JSON.stringify(array_2));
+TestStringify(expected_1, array_1);
+TestStringify(expected_2, array_2);
// Test JSValue with custom prototype.
var num_wrapper = Object(42);
num_wrapper.__proto__ = { __proto__: null,
toString: function() { return true; } };
-assertEquals('1', JSON.stringify(num_wrapper));
+TestStringify('1', num_wrapper);
var str_wrapper = Object('2');
str_wrapper.__proto__ = { __proto__: null,
toString: function() { return true; } };
-assertEquals('"true"', JSON.stringify(str_wrapper));
+TestStringify('"true"', str_wrapper);
var bool_wrapper = Object(false);
bool_wrapper.__proto__ = { __proto__: null,
toString: function() { return true; } };
// Note that toString function is not evaluated here!
-assertEquals('false', JSON.stringify(bool_wrapper));
+TestStringify('false', bool_wrapper);
// Test getters.
var counter = 0;
@@ -68,8 +74,8 @@ var getter_obj = { get getter() {
counter++;
return 123;
} };
-assertEquals('{"getter":123}', JSON.stringify(getter_obj));
-assertEquals(1, counter);
+TestStringify('{"getter":123}', getter_obj);
+assertEquals(2, counter);
// Test toJSON function.
var tojson_obj = { toJSON: function() {
@@ -77,8 +83,8 @@ var tojson_obj = { toJSON: function() {
return [1, 2];
},
a: 1};
-assertEquals('[1,2]', JSON.stringify(tojson_obj));
-assertEquals(2, counter);
+TestStringify('[1,2]', tojson_obj);
+assertEquals(4, counter);
// Test that we don't recursively look for the toJSON function.
var tojson_proto_obj = { a: 'fail' };
@@ -86,7 +92,7 @@ tojson_proto_obj.__proto__ = { toJSON: function() {
counter++;
return tojson_obj;
} };
-assertEquals('{"a":1}', JSON.stringify(tojson_proto_obj));
+TestStringify('{"a":1}', tojson_proto_obj);
// Test toJSON produced by a getter.
var tojson_via_getter = { get toJSON() {
@@ -96,43 +102,44 @@ var tojson_via_getter = { get toJSON() {
};
},
a: 1 };
-assertEquals('321', JSON.stringify(tojson_via_getter));
+TestStringify('321', tojson_via_getter);
// Test toJSON with key.
tojson_obj = { toJSON: function(key) { return key + key; } };
var tojson_with_key_1 = { a: tojson_obj, b: tojson_obj };
-assertEquals('{"a":"aa","b":"bb"}', JSON.stringify(tojson_with_key_1));
+TestStringify('{"a":"aa","b":"bb"}', tojson_with_key_1);
var tojson_with_key_2 = [ tojson_obj, tojson_obj ];
-assertEquals('["00","11"]', JSON.stringify(tojson_with_key_2));
+TestStringify('["00","11"]', tojson_with_key_2);
// Test toJSON with exception.
var tojson_ex = { toJSON: function(key) { throw "123" } };
assertThrows(function() { JSON.stringify(tojson_ex); });
+assertThrows(function() { JSON.stringify(tojson_ex, null, 0); });
// Test toJSON with access to this.
var obj = { toJSON: function(key) { return this.a + key; }, a: "x" };
-assertEquals('{"y":"xy"}', JSON.stringify({y: obj}));
+TestStringify('{"y":"xy"}', {y: obj});
// Test holes in arrays.
var fast_smi = [1, 2, 3, 4];
fast_smi.__proto__ = [7, 7, 7, 7];
delete fast_smi[2];
assertTrue(%HasFastSmiElements(fast_smi));
-assertEquals("[1,2,7,4]", JSON.stringify(fast_smi));
+TestStringify("[1,2,7,4]", fast_smi);
var fast_double = [1.1, 2, 3, 4];
fast_double.__proto__ = [7, 7, 7, 7];
delete fast_double[2];
assertTrue(%HasFastDoubleElements(fast_double));
-assertEquals("[1.1,2,7,4]", JSON.stringify(fast_double));
+TestStringify("[1.1,2,7,4]", fast_double);
var fast_obj = [1, 2, {}, {}];
fast_obj.__proto__ = [7, 7, 7, 7];
delete fast_obj[2];
assertTrue(%HasFastObjectElements(fast_obj));
-assertEquals("[1,2,7,{}]", JSON.stringify(fast_obj));
+TestStringify("[1,2,7,{}]", fast_obj);
var getter_side_effect = { a: 1,
get b() {
@@ -146,8 +153,28 @@ var getter_side_effect = { a: 1,
assertEquals('{"a":1,"b":2,"d":4}', JSON.stringify(getter_side_effect));
assertEquals('{"b":2,"d":4,"e":5}', JSON.stringify(getter_side_effect));
+getter_side_effect = { a: 1,
+ get b() {
+ delete this.a;
+ delete this.c;
+ this.e = 5;
+ return 2;
+ },
+ c: 3,
+ d: 4 };
+assertEquals('{"a":1,"b":2,"d":4}',
+ JSON.stringify(getter_side_effect, null, 0));
+assertEquals('{"b":2,"d":4,"e":5}',
+ JSON.stringify(getter_side_effect, null, 0));
+
var non_enum = {};
non_enum.a = 1;
Object.defineProperty(non_enum, "b", { value: 2, enumerable: false });
non_enum.c = 3;
-assertEquals('{"a":1,"c":3}', JSON.stringify(non_enum));
+TestStringify('{"a":1,"c":3}', non_enum);
+
+var str = "external";
+try {
+ externalizeString(str, true);
+} catch (e) { }
+TestStringify("\"external\"", str, null, 0);
diff --git a/deps/v8/test/mjsunit/nans.js b/deps/v8/test/mjsunit/nans.js
new file mode 100644
index 000000000..d212afdee
--- /dev/null
+++ b/deps/v8/test/mjsunit/nans.js
@@ -0,0 +1,103 @@
+// Copyright 2013 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
+
+
+// Test that both kinds of NaNs (signaling or quiet) do not signal
+
+function TestAllModes(f) {
+ f(); // Runtime
+ f(); // IC
+ f(); // IC second time
+ %OptimizeFunctionOnNextCall(f);
+ f(); // hydrogen
+}
+
+function TestDoubleSignalingNan() {
+ // NaN with signal bit set
+ function f() {
+ var bytes = new Uint32Array([1, 0x7FF00000]);
+ var doubles = new Float64Array(bytes.buffer);
+ assertTrue(isNaN(doubles[0]));
+ assertTrue(isNaN(doubles[0]*2.0));
+ assertTrue(isNaN(doubles[0] + 0.5));
+ }
+
+ TestAllModes(f);
+}
+
+TestDoubleSignalingNan();
+
+function TestDoubleQuietNan() {
+ // NaN with signal bit cleared
+ function f() {
+ var bytes = new Uint32Array([0, 0x7FF80000]);
+ var doubles = new Float64Array(bytes.buffer);
+ assertTrue(isNaN(doubles[0]));
+ assertTrue(isNaN(doubles[0]*2.0));
+ assertTrue(isNaN(doubles[0] + 0.5));
+ }
+
+ TestAllModes(f);
+}
+
+TestDoubleQuietNan();
+
+function TestFloatSignalingNan() {
+ // NaN with signal bit set
+ function f() {
+ var bytes = new Uint32Array([0x7F800001]);
+ var floats = new Float32Array(bytes.buffer);
+ assertTrue(isNaN(floats[0]));
+ assertTrue(isNaN(floats[0]*2.0));
+ assertTrue(isNaN(floats[0] + 0.5));
+ }
+
+ TestAllModes(f);
+}
+
+TestFloatSignalingNan();
+
+function TestFloatQuietNan() {
+ // NaN with signal bit cleared
+ function f() {
+ var bytes = new Uint32Array([0x7FC00000]);
+ var floats = new Float32Array(bytes.buffer);
+ assertTrue(isNaN(floats[0]));
+ assertTrue(isNaN(floats[0]*2.0));
+ assertTrue(isNaN(floats[0] + 0.5));
+ }
+
+ TestAllModes(f);
+}
+
+TestFloatQuietNan();
+
+
+
+
diff --git a/deps/v8/test/mjsunit/regress/external-and-normal-array-polymorphism.js b/deps/v8/test/mjsunit/regress/external-and-normal-array-polymorphism.js
new file mode 100644
index 000000000..0ac1545ca
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/external-and-normal-array-polymorphism.js
@@ -0,0 +1,48 @@
+// Copyright 2013 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.
+
+function store_generator(compare) {
+ return function(a,i,v) {
+ a[i] = v;
+ assertEquals(compare, a[i]);
+ assertEquals(compare, a[i]);
+ }
+}
+
+f = store_generator(5);
+a = [0,0,0];
+f(a,0,5);
+a = [0,0,0];
+f(a,1,5);
+a = [0,0,0];
+f(a,2,5);
+
+f = store_generator(5.5);
+a = new Float32Array(5);
+f(a,0,5.5);
+f(a,1,5.5);
+f(a,2,5.5);
diff --git a/deps/v8/test/mjsunit/regress/negative_lookup.js b/deps/v8/test/mjsunit/regress/negative_lookup.js
new file mode 100644
index 000000000..e23e365fc
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/negative_lookup.js
@@ -0,0 +1,65 @@
+// Copyright 2013 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.
+
+function s(v) {
+ v.x = 1;
+}
+
+function c(p) {
+ return {__proto__: p};
+}
+
+var p = {};
+
+// Make p the last prototype in the chain.
+p.__proto__ = null;
+
+var o1 = c(p);
+var o2 = c(p);
+var o3 = c(p);
+var o4 = c(p);
+
+// Make y go to slow mode.
+// Do this after using p as prototype, since using an object as prototype kicks
+// it back into fast mode.
+p.y = 1;
+delete p.y;
+
+// Initialize the store IC.
+s(o1);
+s(o2);
+
+// Do something with x in slow-mode p.
+Object.defineProperty(p, "x", { writable: false, value: 5 });
+
+// Verify that directly setting x fails.
+o3.x = 10;
+assertEquals(5, o3.x);
+
+// Verify that setting x through the IC fails.
+s(o4);
+assertEquals(5, o4.x);
diff --git a/deps/v8/test/mjsunit/regress/readonly1.js b/deps/v8/test/mjsunit/regress/readonly1.js
new file mode 100644
index 000000000..366f432fb
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/readonly1.js
@@ -0,0 +1,71 @@
+// Copyright 2013 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.
+
+function s(v) {
+ v.x = 1;
+}
+
+function s_strict(v) {
+ "use strict";
+ v.x = 1;
+}
+
+function c(p) {
+ return {__proto__: p};
+}
+
+var p = {};
+
+var o1 = c(p);
+var o2 = c(p);
+var o3 = c(p);
+var o4 = c(p);
+
+// Make p go slow.
+// Do this after using p as prototype, since using an object as prototype kicks
+// it back into fast mode.
+p.y = 1;
+delete p.y;
+p.x = 5;
+
+// Initialize the store IC.
+s(o1);
+s(o2);
+s_strict(o1);
+s_strict(o2);
+
+// Make x non-writable.
+Object.defineProperty(p, "x", { writable: false });
+
+// Verify that direct setting fails.
+o3.x = 20;
+assertEquals(5, o3.x);
+
+// Verify that setting through the IC fails.
+s(o4);
+assertEquals(5, o4.x);
+assertThrows("s_strict(o4);", TypeError);
diff --git a/deps/v8/test/mjsunit/regress/readonly2.js b/deps/v8/test/mjsunit/regress/readonly2.js
new file mode 100644
index 000000000..4e539250d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/readonly2.js
@@ -0,0 +1,62 @@
+// Copyright 2013 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.
+
+Object.defineProperty(this, "x", { writable:true });
+
+function s(v) {
+ v.x = 1;
+}
+
+function s_strict(v) {
+ "use strict";
+ v.x = 1;
+}
+
+function c(p) {
+ return {__proto__: p};
+}
+
+var o1 = c(this);
+var o2 = c(this);
+
+// Initialize the store IC.
+s(c(this));
+s(c(this));
+s_strict(c(this));
+s_strict(c(this));
+
+// Make x non-writable.
+Object.defineProperty(this, "x", { writable:false, value:5 });
+
+// Verify that direct setting fails.
+o1.x = 20;
+assertEquals(5, o1.x);
+
+// Verify that setting through the IC fails.
+s(o2);
+assertEquals(5, o2.x);
+assertThrows("s_strict(o2);", TypeError);
diff --git a/deps/v8/test/mjsunit/regress/readonly3.js b/deps/v8/test/mjsunit/regress/readonly3.js
new file mode 100644
index 000000000..f81979d27
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/readonly3.js
@@ -0,0 +1,65 @@
+// Copyright 2013 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.
+
+this.x = 0;
+
+var p = {};
+Object.defineProperty(p, "x", {writable:false, value:5});
+this.__proto__ = p;
+
+function s(v) {
+ v.x = 1;
+}
+
+function s_strict(v) {
+ "use strict";
+ v.x = 1;
+}
+
+function c(p) {
+ return {__proto__: p};
+}
+
+var o1 = c(this);
+var o2 = c(this);
+
+// Initialize the store IC.
+s(c(this));
+s(c(this));
+s_strict(c(this));
+s_strict(c(this));
+
+delete this.x;
+
+// Verify that direct setting fails.
+o1.x = 20;
+assertEquals(5, o1.x);
+
+// Verify that setting through the IC fails.
+s(o2);
+assertEquals(5, o2.x);
+assertThrows("s_strict(o2);", TypeError);
diff --git a/deps/v8/test/mjsunit/regress/readonly4.js b/deps/v8/test/mjsunit/regress/readonly4.js
new file mode 100644
index 000000000..b2fde2953
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/readonly4.js
@@ -0,0 +1,74 @@
+// Copyright 2013 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.
+
+var slow = {};
+var p = {};
+
+slow.__proto__ = p;
+slow.x = 10;
+slow.y = 10;
+Object.defineProperty(p, "x", {writable:false, value:5});
+
+function c(p) {
+ return {__proto__: p};
+}
+
+function s(v) {
+ return v.x = 1;
+}
+
+function s_strict(v) {
+ "use strict";
+ v.x = 1;
+}
+
+var o1 = c(slow);
+var o2 = c(slow);
+var o1_strict = c(slow);
+var o2_strict = c(slow);
+var o3 = c(slow);
+var o4 = c(slow);
+
+// Make s slow.
+// Do this after using slow as prototype, since using an object as prototype
+// kicks it back into fast mode.
+delete slow.y;
+
+s(o1);
+s(o2);
+s_strict(o1_strict);
+s_strict(o2_strict);
+
+delete slow.x;
+// Directly setting x should fail.
+o3.x = 20
+assertEquals(5, o3.x);
+
+// Setting x through IC should fail.
+s(o4);
+assertEquals(5, o4.x);
+assertThrows("s_strict(o4);", TypeError);
diff --git a/deps/v8/test/mjsunit/regress/regress-105.js b/deps/v8/test/mjsunit/regress/regress-105.js
new file mode 100644
index 000000000..9a4d5c474
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-105.js
@@ -0,0 +1,44 @@
+// Copyright 2013 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.
+
+var custom_valueOf = function() {
+ assertEquals(Number, custom_valueOf.caller);
+ return 2;
+}
+
+var custom_toString = function() {
+ assertEquals(String, custom_toString.caller);
+ return "I used to be an adventurer like you";
+}
+
+var object = {};
+object.valueOf = custom_valueOf;
+object.toString = custom_toString;
+
+assertEquals(2, Number(object));
+assertEquals('I', String(object)[0]);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-166379.js b/deps/v8/test/mjsunit/regress/regress-166379.js
index 2cda61182..b19afbdde 100644
--- a/deps/v8/test/mjsunit/regress/regress-166379.js
+++ b/deps/v8/test/mjsunit/regress/regress-166379.js
@@ -36,3 +36,4 @@ assertEquals(1, mod(3, 2));
// Surprise mod with overflow.
assertEquals(-Infinity, 1/mod(-2147483648, -1));
+
diff --git a/deps/v8/test/mjsunit/regress/regress-201590.js b/deps/v8/test/mjsunit/regress/regress-201590.js
new file mode 100644
index 000000000..0e7ba5723
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-201590.js
@@ -0,0 +1,66 @@
+// Copyright 2013 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
+
+var gdpRatio = 16/9;
+
+function Foo(initialX, initialY, initialScale, initialMapHeight) {
+ this.ORIGIN = { x: initialX, y: initialY };
+ this.scale = initialScale;
+ this.mapHeight = initialMapHeight;
+}
+
+Foo.prototype.bar = function (x, y, xOffset, yOffset) {
+ var tileHeight = 64 * 0.25 * this.scale,
+ tileWidth = 128 * 0.25 * this.scale,
+ xOffset = xOffset * 0.5 || 0,
+ yOffset = yOffset * 0.5 || 0;
+ var xPos = ((xOffset) * gdpRatio) + this.ORIGIN.x * this.scale -
+ ((y * tileWidth ) * gdpRatio) + ((x * tileWidth ) * gdpRatio);
+ var yPos = ((yOffset) * gdpRatio) + this.ORIGIN.y * this.scale +
+ ((y * tileHeight) * gdpRatio) + ((x * tileHeight) * gdpRatio);
+ xPos = xPos - Math.round(((tileWidth) * gdpRatio)) +
+ this.mapHeight * Math.round(((tileWidth) * gdpRatio));
+ return {
+ x: Math.floor(xPos),
+ y: Math.floor(yPos)
+ };
+}
+
+var f = new Foo(10, 20, 2.5, 400);
+
+function baz() {
+ var b = f.bar(1.1, 2.2, 3.3, 4.4);
+ assertEquals(56529, b.x);
+ assertEquals(288, b.y);
+}
+
+baz();
+baz();
+%OptimizeFunctionOnNextCall(Foo.prototype.bar);
+baz();
diff --git a/deps/v8/test/mjsunit/regress/regress-2374.js b/deps/v8/test/mjsunit/regress/regress-2374.js
index b12e5f28c..b333720ac 100644
--- a/deps/v8/test/mjsunit/regress/regress-2374.js
+++ b/deps/v8/test/mjsunit/regress/regress-2374.js
@@ -31,3 +31,4 @@ var obj = JSON.parse(msg);
var obj2 = JSON.parse(msg);
assertEquals(JSON.stringify(obj), JSON.stringify(obj2));
+assertEquals(JSON.stringify(obj, null, 0), JSON.stringify(obj2)); \ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regress/regress-2419.js b/deps/v8/test/mjsunit/regress/regress-2419.js
index 4ffafbe6e..9cd453a58 100644
--- a/deps/v8/test/mjsunit/regress/regress-2419.js
+++ b/deps/v8/test/mjsunit/regress/regress-2419.js
@@ -34,3 +34,4 @@ var b = {0: 5, 1: 4, 2: 3, 3: 2, 4: 1, 5: 0, length: 6};
Object.freeze(b);
Array.prototype.sort.call(b);
assertPropertiesEqual({0: 5, 1: 4, 2: 3, 3: 2, 4: 1, 5: 0, length: 6}, b);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-2438.js b/deps/v8/test/mjsunit/regress/regress-2438.js
index 7be7e7168..3f4fd7df5 100644
--- a/deps/v8/test/mjsunit/regress/regress-2438.js
+++ b/deps/v8/test/mjsunit/regress/regress-2438.js
@@ -49,3 +49,4 @@ testSideEffects("zzzz", /a/);
testSideEffects("zzzz", /a/g);
testSideEffects("xaxa", /a/);
testSideEffects("xaxa", /a/g);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-2444.js b/deps/v8/test/mjsunit/regress/regress-2444.js
index 41b6a95e7..8fb8d8b52 100644
--- a/deps/v8/test/mjsunit/regress/regress-2444.js
+++ b/deps/v8/test/mjsunit/regress/regress-2444.js
@@ -116,3 +116,5 @@ assertEquals(0,
object_factory(1, 0, [1, 0, 0]),
object_factory(2, 1, [1, 1, 0])));
assertFlags([1, 1, 1]);
+
+
diff --git a/deps/v8/test/mjsunit/regress/regress-2451.js b/deps/v8/test/mjsunit/regress/regress-2451.js
index cc087e75e..465e4e68c 100644
--- a/deps/v8/test/mjsunit/regress/regress-2451.js
+++ b/deps/v8/test/mjsunit/regress/regress-2451.js
@@ -38,3 +38,4 @@ f();
%OptimizeFunctionOnNextCall(f);
f();
assertTrue(%GetOptimizationStatus(f) != 2);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-2564.js b/deps/v8/test/mjsunit/regress/regress-2564.js
new file mode 100644
index 000000000..1d7cdaeae
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-2564.js
@@ -0,0 +1,122 @@
+// Copyright 2013 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.
+
+var o = [ function f0() { throw new Error(); },
+ function f1() { o[0](); },
+ function f2() { o[1](); },
+ function f3() { o[2](); } ];
+
+Error.prepareStackTrace = function(error, frames) {
+ Error.prepareStackTrace = undefined; // Prevent recursion.
+ try {
+ assertEquals(5, frames.length);
+ // Don't check the last frame since that's the top-level code.
+ for (var i = 0; i < frames.length - 1; i++) {
+ assertEquals(o[i], frames[i].getFunction());
+ assertEquals(o, frames[i].getThis());
+ // Private fields are no longer accessible.
+ assertEquals(undefined, frames[i].receiver);
+ assertEquals(undefined, frames[i].fun);
+ assertEquals(undefined, frames[i].pos);
+ }
+ return "success";
+ } catch (e) {
+ return "fail";
+ }
+}
+
+try {
+ o[3]();
+} catch (e) {
+ assertEquals("success", e.stack);
+};
+
+
+var o = [ function f0() { throw new Error(); },
+ function f1() { o[0](); },
+ function f2() { "use strict"; o[1](); },
+ function f3() { o[2](); } ];
+
+Error.prepareStackTrace = function(error, frames) {
+ Error.prepareStackTrace = undefined; // Prevent recursion.
+ try {
+ assertEquals(5, frames.length);
+ for (var i = 0; i < 2; i++) {
+ // The first two frames are still classic mode.
+ assertEquals(o[i], frames[i].getFunction());
+ assertEquals(o, frames[i].getThis());
+ }
+ for (var i = 2; i < frames.length; i++) {
+ // The rest are poisoned by the first strict mode function.
+ assertEquals(undefined, frames[i].getFunction());
+ assertEquals(undefined, frames[i].getThis());
+ }
+ for (var i = 0; i < frames.length - 1; i++) {
+ // Function name remains accessible.
+ assertEquals("f"+i, frames[i].getFunctionName());
+ }
+ return "success";
+ } catch (e) {
+ return e;
+ }
+}
+
+try {
+ o[3]();
+} catch (e) {
+ assertEquals("success", e.stack);
+};
+
+
+var o = [ function f0() { "use strict"; throw new Error(); },
+ function f1() { o[0](); },
+ function f2() { o[1](); },
+ function f3() { o[2](); } ];
+
+Error.prepareStackTrace = function(error, frames) {
+ Error.prepareStackTrace = undefined; // Prevent recursion.
+ try {
+ assertEquals(5, frames.length);
+ for (var i = 0; i < frames.length; i++) {
+ // The rest are poisoned by the first strict mode function.
+ assertEquals(undefined, frames[i].getFunction());
+ assertEquals(undefined, frames[i].getThis());
+ if (i < frames.length - 1) { // Function name remains accessible.
+ assertEquals("f"+i, frames[i].getFunctionName());
+ }
+ }
+ return "success";
+ } catch (e) {
+ return e;
+ }
+}
+
+try {
+ o[3]();
+} catch (e) {
+ assertEquals("success", e.stack);
+};
diff --git a/deps/v8/test/mjsunit/regress/regress-2570.js b/deps/v8/test/mjsunit/regress/regress-2570.js
index f9060e8c0..4e32a21e4 100644
--- a/deps/v8/test/mjsunit/regress/regress-2570.js
+++ b/deps/v8/test/mjsunit/regress/regress-2570.js
@@ -29,3 +29,4 @@ var o = ["\u56e7", // Switch JSON stringifier to two-byte mode.
"\u00e6"]; // Latin-1 character.
assertEquals('["\u56e7","\u00e6"]', JSON.stringify(o));
+assertEquals('["\u56e7","\u00e6"]', JSON.stringify(o, null, 0)); \ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regress/regress-2593.js b/deps/v8/test/mjsunit/regress/regress-2593.js
new file mode 100644
index 000000000..b51b41c27
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-2593.js
@@ -0,0 +1,61 @@
+// Copyright 2013 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_gc
+
+p1 = { };
+p2 = { };
+p3 = { x : 1 };
+p2.__proto__ = p3
+p1.__proto__ = p2
+
+// Normalize p1.
+p1.z = 1
+delete p1.z
+
+// Make sure all objects are in old space.
+for (var i = 0; i < 10; i++) gc();
+
+function f2() {
+ p2.x;
+}
+
+function f1() {
+ return p1.x;
+}
+
+// Create load stub in p2.
+for (var i = 0; i < 10; i++) f2();
+
+// Create load stub in p2 for p1.
+for (var i = 0; i < 10; i++) f1();
+
+assertEquals(1, f1());
+
+p2.x = 2;
+
+assertEquals(2, f1());
diff --git a/deps/v8/test/mjsunit/regress/regress-2596.js b/deps/v8/test/mjsunit/regress/regress-2596.js
new file mode 100644
index 000000000..1d327fe0f
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-2596.js
@@ -0,0 +1,56 @@
+// Copyright 2013 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
+
+var bytes = new Uint8Array([
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]); // kHoleNaN
+var doubles = new Float64Array(bytes.buffer);
+assertTrue(isNaN(doubles[0]));
+
+var prototype = [2.5, 2.5];
+var array = [3.5, 3.5];
+array.__proto__ = prototype;
+assertTrue(%HasFastDoubleElements(array));
+
+function boom(index) {
+ array[index] = doubles[0];
+ return array[index];
+}
+
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+
+// Test hydrogen
+%OptimizeFunctionOnNextCall(boom);
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+
+
+
diff --git a/deps/v8/test/mjsunit/regress/regress-753.js b/deps/v8/test/mjsunit/regress/regress-753.js
index 6a6d87bb0..4621de6ba 100644
--- a/deps/v8/test/mjsunit/regress/regress-753.js
+++ b/deps/v8/test/mjsunit/regress/regress-753.js
@@ -32,5 +32,5 @@
// See: http://code.google.com/p/v8/issues/detail?id=753
var obj = {a1: {b1: [1,2,3,4], b2: {c1: 1, c2: 2}},a2: 'a2'};
-assertEquals(JSON.stringify(obj,null, 5.99999), JSON.stringify(obj,null, 5));
+assertEquals(JSON.stringify(obj, null, 5.99999), JSON.stringify(obj, null, 5));
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-146910.js b/deps/v8/test/mjsunit/regress/regress-crbug-146910.js
index 1b2a60af7..120f80973 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-146910.js
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-146910.js
@@ -1,4 +1,4 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -25,9 +25,14 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-assertEquals(String.fromCharCode(97, 220, 256), 'a' + '\u00DC' + '\u0100');
-assertEquals(String.fromCharCode(97, 220, 256), 'a\u00DC\u0100');
+var x = [];
+assertSame(0, x.length);
+assertSame(undefined, x[0]);
-assertEquals(['a', 'b', '\xdc'], ['b', '\xdc', 'a'].sort());
-assertEquals(['\xfc\xdc', '\xfc'], new RegExp('(\xdc)\\1', 'i').exec('\xfc\xdc'));
+Object.defineProperty(x, '0', { value: 7, configurable: false });
+assertSame(1, x.length);
+assertSame(7, x[0]);
+x.length = 0;
+assertSame(1, x.length);
+assertSame(7, x[0]);
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-158185.js b/deps/v8/test/mjsunit/regress/regress-crbug-158185.js
index 5cb5900c8..99f19c72f 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-158185.js
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-158185.js
@@ -36,3 +36,4 @@ assertEquals("12A",
assertEquals(1, JSON.parse('{"0":1}')[0]);
assertEquals(undefined, JSON.parse('{"00":1}')[0]);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-171715.js b/deps/v8/test/mjsunit/regress/regress-crbug-171715.js
new file mode 100644
index 000000000..040c381e3
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-171715.js
@@ -0,0 +1,87 @@
+// Copyright 2013 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
+
+Debug = debug.Debug
+
+var error = null;
+var test = 0;
+
+function check_v(expected, exec_state, frame_id) {
+ assertEquals(expected, exec_state.frame(frame_id).evaluate('v').value());
+}
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event != Debug.DebugEvent.Break) return;
+ test++;
+ if (test == 1) {
+ check_v('inner0', exec_state, 0);
+ check_v('inner0', exec_state, 1);
+ check_v('outer', exec_state, 2);
+ assertArrayEquals(["a", "b", "c"],
+ exec_state.frame(0).evaluate('arguments').value());
+ } else if (test == 2) {
+ check_v('inner1', exec_state, 0);
+ check_v('inner1', exec_state, 1);
+ check_v('outer', exec_state, 2);
+ assertArrayEquals(["a", "b", "c"],
+ exec_state.frame(0).evaluate('arguments').value());
+ } else {
+ assertEquals(3, test);
+ check_v('inner2', exec_state, 0);
+ check_v('inner1', exec_state, 1);
+ check_v('inner1', exec_state, 2);
+ check_v('outer', exec_state, 3);
+ assertArrayEquals(["x", "y", "z"],
+ exec_state.frame(0).evaluate('arguments').value());
+ assertArrayEquals(["a", "b", "c"],
+ exec_state.frame(1).evaluate('arguments').value());
+ }
+ } catch (e) {
+ error = e;
+ }
+};
+
+Debug.setListener(listener);
+
+var v = 'outer';
+(function() { // Test 1 and 2
+ var v = 'inner0';
+ eval("debugger; var v = 'inner1'; debugger;");
+ assertEquals('inner1', v); // Overwritten by local eval.
+})("a", "b", "c");
+assertNull(error);
+
+(function() { // Test 3
+ var v = 'inner0'; // Local eval overwrites this value.
+ eval("var v = 'inner1'; " +
+ "(function() { var v = 'inner2'; debugger; })('x', 'y', 'z');");
+ assertEquals('inner1', v); // Overwritten by local eval.
+})("a", "b", "c");
+assertNull(error);
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-178790.js b/deps/v8/test/mjsunit/regress/regress-crbug-178790.js
index 25cc96b85..57071eaa0 100644
--- a/deps/v8/test/mjsunit/regress/regress-crbug-178790.js
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-178790.js
@@ -49,3 +49,4 @@ for (var i = 0; i < 1000; i++) {
r3 = "(" + r3 + ")a";
}
"test".match(RegExp(r3));
+
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-217858.js b/deps/v8/test/mjsunit/regress/regress-crbug-217858.js
new file mode 100644
index 000000000..8563e07ee
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-217858.js
@@ -0,0 +1,40 @@
+// Copyright 2013 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
+
+var r = /r/;
+var a = "";
+function f() {
+ %OptimizeFunctionOnNextCall(f, "osr");
+ for (var i = 0; i < 1000000; i++) {
+ a += i.toString();
+ r[r] = function() {};
+ }
+}
+
+f();
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-222893.js b/deps/v8/test/mjsunit/regress/regress-crbug-222893.js
new file mode 100644
index 000000000..d5baa7b25
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-222893.js
@@ -0,0 +1,64 @@
+// Copyright 2013 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
+
+Debug = debug.Debug
+
+var error = null;
+var array = ["a", "b", "c"];
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ assertArrayEquals(array,
+ exec_state.frame(0).evaluate('arguments').value());
+ }
+ } catch (e) {
+ error = e;
+ }
+};
+
+Debug.setListener(listener);
+
+
+function f(a, b) {
+ arguments;
+ debugger; // Arguments object is already materialized.
+}
+
+f.apply(this, array);
+f("a", "b", "c");
+assertNull(error);
+
+function g(a, b) {
+ debugger; // Arguments object is not yet materialized.
+}
+g.apply(this, array);
+g("a", "b", "c");
+assertNull(error);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-json-stringify-gc.js b/deps/v8/test/mjsunit/regress/regress-json-stringify-gc.js
index 46c3dbf12..c0a71bf4a 100644
--- a/deps/v8/test/mjsunit/regress/regress-json-stringify-gc.js
+++ b/deps/v8/test/mjsunit/regress/regress-json-stringify-gc.js
@@ -38,3 +38,4 @@ for (var i = 0; i < 10000; i++) a.push(new_space_string);
json1 = JSON.stringify(a);
json2 = JSON.stringify(a);
assertTrue(json1 == json2, "GC caused JSON.stringify to fail.");
+
diff --git a/deps/v8/test/mjsunit/regress/regress-latin-1.js b/deps/v8/test/mjsunit/regress/regress-latin-1.js
index a988ebd36..e7f31366c 100644
--- a/deps/v8/test/mjsunit/regress/regress-latin-1.js
+++ b/deps/v8/test/mjsunit/regress/regress-latin-1.js
@@ -29,6 +29,7 @@ assertEquals(String.fromCharCode(97, 220, 256), 'a' + '\u00DC' + '\u0100');
assertEquals(String.fromCharCode(97, 220, 256), 'a\u00DC\u0100');
assertEquals(0x80, JSON.stringify("\x80").charCodeAt(1));
+assertEquals(0x80, JSON.stringify("\x80", 0, null).charCodeAt(1));
assertEquals(['a', 'b', '\xdc'], ['b', '\xdc', 'a'].sort());
diff --git a/deps/v8/test/mjsunit/regress/setter.js b/deps/v8/test/mjsunit/regress/setter.js
new file mode 100644
index 000000000..e3a8000f2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/setter.js
@@ -0,0 +1,66 @@
+// Copyright 2013 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.
+
+function s(v) {
+ v.x = 1;
+}
+
+function c(p) {
+ return {__proto__: p};
+}
+
+var p = {};
+
+var o1 = c(p);
+var o2 = c(p);
+var o3 = c(p);
+var o4 = c(p);
+var o5 = c(p);
+
+// Initialize the store IC.
+s(o1);
+s(o2);
+
+// Install a setter on p.x
+var count = 0;
+Object.defineProperty(p, "x", {
+ set: function(x) {
+ count += 1;
+ }
+});
+
+// Verify that the setter was called directly.
+o3.x = 20;
+assertEquals(1, count);
+
+// Verify that monomorphic prototype failure is triggered in the IC.
+s(o4);
+assertEquals(2, count);
+
+// Verify that the newly installed IC is correct.
+s(o5);
+assertEquals(3, count);
diff --git a/deps/v8/test/mjsunit/shift-for-integer-div.js b/deps/v8/test/mjsunit/shift-for-integer-div.js
index d3c9d2b49..0fe126229 100644
--- a/deps/v8/test/mjsunit/shift-for-integer-div.js
+++ b/deps/v8/test/mjsunit/shift-for-integer-div.js
@@ -56,3 +56,4 @@ for (var i = 0; i < 10000; i++) {
var min_int = -(0x7FFFFFFF)-1;
assertEquals(-min_int, divn1(min_int));
+
diff --git a/deps/v8/test/mjsunit/string-natives.js b/deps/v8/test/mjsunit/string-natives.js
index 12fa65dcb..b1ec87542 100644
--- a/deps/v8/test/mjsunit/string-natives.js
+++ b/deps/v8/test/mjsunit/string-natives.js
@@ -69,3 +69,4 @@ test();
test();
%OptimizeFunctionOnNextCall(test);
test();
+
diff --git a/deps/v8/tools/grokdump.py b/deps/v8/tools/grokdump.py
index 7daad21ee..f3ae8a22b 100755
--- a/deps/v8/tools/grokdump.py
+++ b/deps/v8/tools/grokdump.py
@@ -830,82 +830,82 @@ class MinidumpReader(object):
# };
# static P p;
INSTANCE_TYPES = {
- 64: "SYMBOL_TYPE",
- 68: "ASCII_SYMBOL_TYPE",
- 65: "CONS_SYMBOL_TYPE",
- 69: "CONS_ASCII_SYMBOL_TYPE",
- 66: "EXTERNAL_SYMBOL_TYPE",
- 74: "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
- 70: "EXTERNAL_ASCII_SYMBOL_TYPE",
- 82: "SHORT_EXTERNAL_SYMBOL_TYPE",
- 90: "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
- 86: "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE",
0: "STRING_TYPE",
4: "ASCII_STRING_TYPE",
1: "CONS_STRING_TYPE",
5: "CONS_ASCII_STRING_TYPE",
3: "SLICED_STRING_TYPE",
2: "EXTERNAL_STRING_TYPE",
- 10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
6: "EXTERNAL_ASCII_STRING_TYPE",
+ 10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
18: "SHORT_EXTERNAL_STRING_TYPE",
- 26: "SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
22: "SHORT_EXTERNAL_ASCII_STRING_TYPE",
- 6: "PRIVATE_EXTERNAL_ASCII_STRING_TYPE",
- 128: "MAP_TYPE",
- 129: "CODE_TYPE",
- 130: "ODDBALL_TYPE",
- 131: "JS_GLOBAL_PROPERTY_CELL_TYPE",
- 132: "HEAP_NUMBER_TYPE",
- 133: "FOREIGN_TYPE",
- 134: "BYTE_ARRAY_TYPE",
- 135: "FREE_SPACE_TYPE",
- 136: "EXTERNAL_BYTE_ARRAY_TYPE",
- 137: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
- 138: "EXTERNAL_SHORT_ARRAY_TYPE",
- 139: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
- 140: "EXTERNAL_INT_ARRAY_TYPE",
- 141: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
- 142: "EXTERNAL_FLOAT_ARRAY_TYPE",
- 144: "EXTERNAL_PIXEL_ARRAY_TYPE",
- 146: "FILLER_TYPE",
- 147: "DECLARED_ACCESSOR_DESCRIPTOR_TYPE",
- 148: "DECLARED_ACCESSOR_INFO_TYPE",
- 149: "EXECUTABLE_ACCESSOR_INFO_TYPE",
- 150: "ACCESSOR_PAIR_TYPE",
- 151: "ACCESS_CHECK_INFO_TYPE",
- 152: "INTERCEPTOR_INFO_TYPE",
- 153: "CALL_HANDLER_INFO_TYPE",
- 154: "FUNCTION_TEMPLATE_INFO_TYPE",
- 155: "OBJECT_TEMPLATE_INFO_TYPE",
- 156: "SIGNATURE_INFO_TYPE",
- 157: "TYPE_SWITCH_INFO_TYPE",
- 158: "ALLOCATION_SITE_INFO_TYPE",
- 159: "SCRIPT_TYPE",
- 160: "CODE_CACHE_TYPE",
- 161: "POLYMORPHIC_CODE_CACHE_TYPE",
- 162: "TYPE_FEEDBACK_INFO_TYPE",
- 163: "ALIASED_ARGUMENTS_ENTRY_TYPE",
- 166: "FIXED_ARRAY_TYPE",
- 145: "FIXED_DOUBLE_ARRAY_TYPE",
- 167: "SHARED_FUNCTION_INFO_TYPE",
- 168: "JS_MESSAGE_OBJECT_TYPE",
- 171: "JS_VALUE_TYPE",
- 172: "JS_DATE_TYPE",
- 173: "JS_OBJECT_TYPE",
- 174: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
- 175: "JS_MODULE_TYPE",
- 176: "JS_GLOBAL_OBJECT_TYPE",
- 177: "JS_BUILTINS_OBJECT_TYPE",
- 178: "JS_GLOBAL_PROXY_TYPE",
- 179: "JS_ARRAY_TYPE",
- 170: "JS_PROXY_TYPE",
- 182: "JS_WEAK_MAP_TYPE",
- 183: "JS_REGEXP_TYPE",
- 184: "JS_FUNCTION_TYPE",
- 169: "JS_FUNCTION_PROXY_TYPE",
- 164: "DEBUG_INFO_TYPE",
- 165: "BREAK_POINT_INFO_TYPE",
+ 26: "SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
+ 64: "INTERNALIZED_STRING_TYPE",
+ 68: "ASCII_INTERNALIZED_STRING_TYPE",
+ 65: "CONS_INTERNALIZED_STRING_TYPE",
+ 69: "CONS_ASCII_INTERNALIZED_STRING_TYPE",
+ 66: "EXTERNAL_INTERNALIZED_STRING_TYPE",
+ 70: "EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE",
+ 74: "EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE",
+ 82: "SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE",
+ 86: "SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE",
+ 90: "SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE",
+ 128: "SYMBOL_TYPE",
+ 129: "MAP_TYPE",
+ 130: "CODE_TYPE",
+ 131: "ODDBALL_TYPE",
+ 132: "JS_GLOBAL_PROPERTY_CELL_TYPE",
+ 133: "HEAP_NUMBER_TYPE",
+ 134: "FOREIGN_TYPE",
+ 135: "BYTE_ARRAY_TYPE",
+ 136: "FREE_SPACE_TYPE",
+ 137: "EXTERNAL_BYTE_ARRAY_TYPE",
+ 138: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
+ 139: "EXTERNAL_SHORT_ARRAY_TYPE",
+ 140: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
+ 141: "EXTERNAL_INT_ARRAY_TYPE",
+ 142: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
+ 143: "EXTERNAL_FLOAT_ARRAY_TYPE",
+ 145: "EXTERNAL_PIXEL_ARRAY_TYPE",
+ 147: "FILLER_TYPE",
+ 148: "DECLARED_ACCESSOR_DESCRIPTOR_TYPE",
+ 149: "DECLARED_ACCESSOR_INFO_TYPE",
+ 150: "EXECUTABLE_ACCESSOR_INFO_TYPE",
+ 151: "ACCESSOR_PAIR_TYPE",
+ 152: "ACCESS_CHECK_INFO_TYPE",
+ 153: "INTERCEPTOR_INFO_TYPE",
+ 154: "CALL_HANDLER_INFO_TYPE",
+ 155: "FUNCTION_TEMPLATE_INFO_TYPE",
+ 156: "OBJECT_TEMPLATE_INFO_TYPE",
+ 157: "SIGNATURE_INFO_TYPE",
+ 158: "TYPE_SWITCH_INFO_TYPE",
+ 159: "ALLOCATION_SITE_INFO_TYPE",
+ 160: "SCRIPT_TYPE",
+ 161: "CODE_CACHE_TYPE",
+ 162: "POLYMORPHIC_CODE_CACHE_TYPE",
+ 163: "TYPE_FEEDBACK_INFO_TYPE",
+ 164: "ALIASED_ARGUMENTS_ENTRY_TYPE",
+ 167: "FIXED_ARRAY_TYPE",
+ 146: "FIXED_DOUBLE_ARRAY_TYPE",
+ 168: "SHARED_FUNCTION_INFO_TYPE",
+ 169: "JS_MESSAGE_OBJECT_TYPE",
+ 172: "JS_VALUE_TYPE",
+ 173: "JS_DATE_TYPE",
+ 174: "JS_OBJECT_TYPE",
+ 175: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
+ 176: "JS_MODULE_TYPE",
+ 177: "JS_GLOBAL_OBJECT_TYPE",
+ 178: "JS_BUILTINS_OBJECT_TYPE",
+ 179: "JS_GLOBAL_PROXY_TYPE",
+ 180: "JS_ARRAY_TYPE",
+ 171: "JS_PROXY_TYPE",
+ 183: "JS_WEAK_MAP_TYPE",
+ 184: "JS_REGEXP_TYPE",
+ 185: "JS_FUNCTION_TYPE",
+ 170: "JS_FUNCTION_PROXY_TYPE",
+ 165: "DEBUG_INFO_TYPE",
+ 166: "BREAK_POINT_INFO_TYPE",
}
@@ -931,86 +931,87 @@ INSTANCE_TYPES = {
# }
# printf("}\n");
KNOWN_MAPS = {
- 0x08081: (134, "ByteArrayMap"),
- 0x080a9: (128, "MetaMap"),
- 0x080d1: (130, "OddballMap"),
- 0x080f9: (68, "AsciiSymbolMap"),
- 0x08121: (166, "FixedArrayMap"),
- 0x08149: (132, "HeapNumberMap"),
- 0x08171: (135, "FreeSpaceMap"),
- 0x08199: (146, "OnePointerFillerMap"),
- 0x081c1: (146, "TwoPointerFillerMap"),
- 0x081e9: (131, "GlobalPropertyCellMap"),
- 0x08211: (167, "SharedFunctionInfoMap"),
- 0x08239: (4, "AsciiStringMap"),
- 0x08261: (166, "NativeContextMap"),
- 0x08289: (129, "CodeMap"),
- 0x082b1: (166, "ScopeInfoMap"),
- 0x082d9: (166, "FixedCOWArrayMap"),
- 0x08301: (145, "FixedDoubleArrayMap"),
- 0x08329: (166, "HashTableMap"),
+ 0x08081: (135, "ByteArrayMap"),
+ 0x080a9: (129, "MetaMap"),
+ 0x080d1: (131, "OddballMap"),
+ 0x080f9: (68, "AsciiInternalizedStringMap"),
+ 0x08121: (167, "FixedArrayMap"),
+ 0x08149: (133, "HeapNumberMap"),
+ 0x08171: (136, "FreeSpaceMap"),
+ 0x08199: (147, "OnePointerFillerMap"),
+ 0x081c1: (147, "TwoPointerFillerMap"),
+ 0x081e9: (132, "GlobalPropertyCellMap"),
+ 0x08211: (168, "SharedFunctionInfoMap"),
+ 0x08239: (167, "NativeContextMap"),
+ 0x08261: (130, "CodeMap"),
+ 0x08289: (167, "ScopeInfoMap"),
+ 0x082b1: (167, "FixedCOWArrayMap"),
+ 0x082d9: (146, "FixedDoubleArrayMap"),
+ 0x08301: (167, "HashTableMap"),
+ 0x08329: (128, "SymbolMap"),
0x08351: (0, "StringMap"),
- 0x08379: (64, "SymbolMap"),
+ 0x08379: (4, "AsciiStringMap"),
0x083a1: (1, "ConsStringMap"),
0x083c9: (5, "ConsAsciiStringMap"),
0x083f1: (3, "SlicedStringMap"),
0x08419: (7, "SlicedAsciiStringMap"),
- 0x08441: (65, "ConsSymbolMap"),
- 0x08469: (69, "ConsAsciiSymbolMap"),
- 0x08491: (66, "ExternalSymbolMap"),
- 0x084b9: (74, "ExternalSymbolWithAsciiDataMap"),
- 0x084e1: (70, "ExternalAsciiSymbolMap"),
- 0x08509: (2, "ExternalStringMap"),
- 0x08531: (10, "ExternalStringWithAsciiDataMap"),
- 0x08559: (6, "ExternalAsciiStringMap"),
- 0x08581: (82, "ShortExternalSymbolMap"),
- 0x085a9: (90, "ShortExternalSymbolWithAsciiDataMap"),
- 0x085d1: (86, "ShortExternalAsciiSymbolMap"),
- 0x085f9: (18, "ShortExternalStringMap"),
- 0x08621: (26, "ShortExternalStringWithAsciiDataMap"),
- 0x08649: (22, "ShortExternalAsciiStringMap"),
- 0x08671: (0, "UndetectableStringMap"),
- 0x08699: (4, "UndetectableAsciiStringMap"),
- 0x086c1: (144, "ExternalPixelArrayMap"),
- 0x086e9: (136, "ExternalByteArrayMap"),
- 0x08711: (137, "ExternalUnsignedByteArrayMap"),
- 0x08739: (138, "ExternalShortArrayMap"),
- 0x08761: (139, "ExternalUnsignedShortArrayMap"),
- 0x08789: (140, "ExternalIntArrayMap"),
- 0x087b1: (141, "ExternalUnsignedIntArrayMap"),
- 0x087d9: (142, "ExternalFloatArrayMap"),
- 0x08801: (143, "ExternalDoubleArrayMap"),
- 0x08829: (166, "NonStrictArgumentsElementsMap"),
- 0x08851: (166, "FunctionContextMap"),
- 0x08879: (166, "CatchContextMap"),
- 0x088a1: (166, "WithContextMap"),
- 0x088c9: (166, "BlockContextMap"),
- 0x088f1: (166, "ModuleContextMap"),
- 0x08919: (166, "GlobalContextMap"),
- 0x08941: (168, "JSMessageObjectMap"),
- 0x08969: (133, "ForeignMap"),
- 0x08991: (173, "NeanderMap"),
- 0x089b9: (158, "AllocationSiteInfoMap"),
- 0x089e1: (161, "PolymorphicCodeCacheMap"),
- 0x08a09: (159, "ScriptMap"),
- 0x08a31: (173, ""),
- 0x08a59: (173, "ExternalMap"),
- 0x08a81: (147, "DeclaredAccessorDescriptorMap"),
- 0x08aa9: (148, "DeclaredAccessorInfoMap"),
- 0x08ad1: (149, "ExecutableAccessorInfoMap"),
- 0x08af9: (150, "AccessorPairMap"),
- 0x08b21: (151, "AccessCheckInfoMap"),
- 0x08b49: (152, "InterceptorInfoMap"),
- 0x08b71: (153, "CallHandlerInfoMap"),
- 0x08b99: (154, "FunctionTemplateInfoMap"),
- 0x08bc1: (155, "ObjectTemplateInfoMap"),
- 0x08be9: (156, "SignatureInfoMap"),
- 0x08c11: (157, "TypeSwitchInfoMap"),
- 0x08c39: (160, "CodeCacheMap"),
- 0x08c61: (162, "TypeFeedbackInfoMap"),
- 0x08c89: (163, "AliasedArgumentsEntryMap"),
- 0x08cb1: (164, "DebugInfoMap"),
- 0x08cd9: (165, "BreakPointInfoMap"),
+ 0x08441: (2, "ExternalStringMap"),
+ 0x08469: (10, "ExternalStringWithAsciiDataMap"),
+ 0x08491: (6, "ExternalAsciiStringMap"),
+ 0x084b9: (18, "ShortExternalStringMap"),
+ 0x084e1: (26, "ShortExternalStringWithAsciiDataMap"),
+ 0x08509: (64, "InternalizedStringMap"),
+ 0x08531: (65, "ConsInternalizedStringMap"),
+ 0x08559: (69, "ConsAsciiInternalizedStringMap"),
+ 0x08581: (66, "ExternalInternalizedStringMap"),
+ 0x085a9: (74, "ExternalInternalizedStringWithAsciiDataMap"),
+ 0x085d1: (70, "ExternalAsciiInternalizedStringMap"),
+ 0x085f9: (82, "ShortExternalInternalizedStringMap"),
+ 0x08621: (90, "ShortExternalInternalizedStringWithAsciiDataMap"),
+ 0x08649: (86, "ShortExternalAsciiInternalizedStringMap"),
+ 0x08671: (22, "ShortExternalAsciiStringMap"),
+ 0x08699: (0, "UndetectableStringMap"),
+ 0x086c1: (4, "UndetectableAsciiStringMap"),
+ 0x086e9: (145, "ExternalPixelArrayMap"),
+ 0x08711: (137, "ExternalByteArrayMap"),
+ 0x08739: (138, "ExternalUnsignedByteArrayMap"),
+ 0x08761: (139, "ExternalShortArrayMap"),
+ 0x08789: (140, "ExternalUnsignedShortArrayMap"),
+ 0x087b1: (141, "ExternalIntArrayMap"),
+ 0x087d9: (142, "ExternalUnsignedIntArrayMap"),
+ 0x08801: (143, "ExternalFloatArrayMap"),
+ 0x08829: (144, "ExternalDoubleArrayMap"),
+ 0x08851: (167, "NonStrictArgumentsElementsMap"),
+ 0x08879: (167, "FunctionContextMap"),
+ 0x088a1: (167, "CatchContextMap"),
+ 0x088c9: (167, "WithContextMap"),
+ 0x088f1: (167, "BlockContextMap"),
+ 0x08919: (167, "ModuleContextMap"),
+ 0x08941: (167, "GlobalContextMap"),
+ 0x08969: (169, "JSMessageObjectMap"),
+ 0x08991: (134, "ForeignMap"),
+ 0x089b9: (174, "NeanderMap"),
+ 0x089e1: (159, "AllocationSiteInfoMap"),
+ 0x08a09: (162, "PolymorphicCodeCacheMap"),
+ 0x08a31: (160, "ScriptMap"),
+ 0x08a59: (174, ""),
+ 0x08a81: (174, "ExternalMap"),
+ 0x08aa9: (148, "DeclaredAccessorDescriptorMap"),
+ 0x08ad1: (149, "DeclaredAccessorInfoMap"),
+ 0x08af9: (150, "ExecutableAccessorInfoMap"),
+ 0x08b21: (151, "AccessorPairMap"),
+ 0x08b49: (152, "AccessCheckInfoMap"),
+ 0x08b71: (153, "InterceptorInfoMap"),
+ 0x08b99: (154, "CallHandlerInfoMap"),
+ 0x08bc1: (155, "FunctionTemplateInfoMap"),
+ 0x08be9: (156, "ObjectTemplateInfoMap"),
+ 0x08c11: (157, "SignatureInfoMap"),
+ 0x08c39: (158, "TypeSwitchInfoMap"),
+ 0x08c61: (161, "CodeCacheMap"),
+ 0x08c89: (163, "TypeFeedbackInfoMap"),
+ 0x08cb1: (164, "AliasedArgumentsEntryMap"),
+ 0x08cd9: (165, "DebugInfoMap"),
+ 0x08d01: (166, "BreakPointInfoMap"),
}
@@ -1932,7 +1933,7 @@ class InspectionShell(cmd.Cmd):
Print a descriptor array in a readable format.
"""
start = int(address, 16)
- if ((start & 1) == 1): start = start + 1
+ if ((start & 1) == 1): start = start - 1
DescriptorArray(FixedArray(self.heap, None, start)).Print(Printer())
def do_do_map(self, address):
diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp
index 2d6eaf9d0..b11755322 100644
--- a/deps/v8/tools/gyp/v8.gyp
+++ b/deps/v8/tools/gyp/v8.gyp
@@ -797,7 +797,8 @@
'../../src/symbol.js',
'../../src/proxy.js',
'../../src/collection.js',
- '../../src/object-observe.js'
+ '../../src/object-observe.js',
+ '../../src/typedarray.js'
],
},
'actions': [