summaryrefslogtreecommitdiff
path: root/chromium/v8
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-11-21 14:09:57 +0100
committerAndras Becsi <andras.becsi@digia.com>2013-11-29 15:14:36 +0100
commiteb32ba6f51d0c21d58cd7d89785285ff8fa64624 (patch)
tree2c7c940e1dbee81b89d935626110816b494aa32c /chromium/v8
parent9427c1a0222ebd67efef1a2c7990a0fa5c9aac84 (diff)
downloadqtwebengine-chromium-eb32ba6f51d0c21d58cd7d89785285ff8fa64624.tar.gz
Update chromium to branch 1599.
Change-Id: I04e775a946a208bb4500d3b722bcb05c82b9d7cb Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/v8')
-rw-r--r--chromium/v8/ChangeLog57
-rw-r--r--chromium/v8/Makefile9
-rwxr-xr-xchromium/v8/include/v8-debug.h36
-rw-r--r--chromium/v8/include/v8-preparser.h44
-rw-r--r--chromium/v8/include/v8-profiler.h69
-rw-r--r--chromium/v8/include/v8-testing.h34
-rw-r--r--chromium/v8/include/v8.h246
-rw-r--r--chromium/v8/src/api.cc67
-rw-r--r--chromium/v8/src/arm/builtins-arm.cc20
-rw-r--r--chromium/v8/src/arm/code-stubs-arm.cc48
-rw-r--r--chromium/v8/src/arm/codegen-arm.cc4
-rw-r--r--chromium/v8/src/arm/debug-arm.cc6
-rw-r--r--chromium/v8/src/arm/full-codegen-arm.cc43
-rw-r--r--chromium/v8/src/arm/lithium-arm.cc149
-rw-r--r--chromium/v8/src/arm/lithium-arm.h106
-rw-r--r--chromium/v8/src/arm/lithium-codegen-arm.cc395
-rw-r--r--chromium/v8/src/arm/lithium-codegen-arm.h36
-rw-r--r--chromium/v8/src/arm/lithium-gap-resolver-arm.cc2
-rw-r--r--chromium/v8/src/arm/macro-assembler-arm.cc70
-rw-r--r--chromium/v8/src/arm/macro-assembler-arm.h8
-rw-r--r--chromium/v8/src/array-iterator.js7
-rw-r--r--chromium/v8/src/assert-scope.h9
-rw-r--r--chromium/v8/src/ast.cc14
-rw-r--r--chromium/v8/src/ast.h34
-rw-r--r--chromium/v8/src/atomicops_internals_tsan.h12
-rw-r--r--chromium/v8/src/bootstrapper.cc5
-rw-r--r--chromium/v8/src/builtins.h2
-rw-r--r--chromium/v8/src/code-stubs-hydrogen.cc59
-rw-r--r--chromium/v8/src/code-stubs.cc91
-rw-r--r--chromium/v8/src/code-stubs.h68
-rw-r--r--chromium/v8/src/compiler.cc39
-rw-r--r--chromium/v8/src/compiler.h23
-rw-r--r--chromium/v8/src/cpu-profiler.cc2
-rw-r--r--chromium/v8/src/cpu-profiler.h2
-rw-r--r--chromium/v8/src/d8.cc72
-rw-r--r--chromium/v8/src/d8.h2
-rw-r--r--chromium/v8/src/debug.cc8
-rw-r--r--chromium/v8/src/deoptimizer.cc352
-rw-r--r--chromium/v8/src/deoptimizer.h57
-rw-r--r--chromium/v8/src/effects.h361
-rw-r--r--chromium/v8/src/execution.cc4
-rw-r--r--chromium/v8/src/extensions/i18n/collator.cc366
-rw-r--r--chromium/v8/src/extensions/i18n/collator.h68
-rw-r--r--chromium/v8/src/extensions/i18n/collator.js11
-rw-r--r--chromium/v8/src/extensions/i18n/date-format.cc329
-rw-r--r--chromium/v8/src/extensions/i18n/date-format.h71
-rw-r--r--chromium/v8/src/extensions/i18n/date-format.js10
-rw-r--r--chromium/v8/src/extensions/i18n/i18n-extension.cc40
-rw-r--r--chromium/v8/src/extensions/i18n/i18n-utils.cc46
-rw-r--r--chromium/v8/src/extensions/i18n/i18n-utils.js11
-rw-r--r--chromium/v8/src/extensions/i18n/locale.cc251
-rw-r--r--chromium/v8/src/extensions/i18n/locale.h56
-rw-r--r--chromium/v8/src/extensions/i18n/locale.js4
-rw-r--r--chromium/v8/src/extensions/i18n/number-format.cc418
-rw-r--r--chromium/v8/src/extensions/i18n/number-format.h69
-rw-r--r--chromium/v8/src/extensions/i18n/number-format.js16
-rw-r--r--chromium/v8/src/factory.cc13
-rw-r--r--chromium/v8/src/factory.h6
-rw-r--r--chromium/v8/src/flag-definitions.h8
-rw-r--r--chromium/v8/src/full-codegen.cc16
-rw-r--r--chromium/v8/src/full-codegen.h64
-rw-r--r--chromium/v8/src/global-handles.cc64
-rw-r--r--chromium/v8/src/global-handles.h71
-rw-r--r--chromium/v8/src/harmony-array.js124
-rw-r--r--chromium/v8/src/heap-snapshot-generator.cc24
-rw-r--r--chromium/v8/src/heap-snapshot-generator.h10
-rw-r--r--chromium/v8/src/heap.cc109
-rw-r--r--chromium/v8/src/heap.h19
-rw-r--r--chromium/v8/src/hydrogen-escape-analysis.cc230
-rw-r--r--chromium/v8/src/hydrogen-escape-analysis.h35
-rw-r--r--chromium/v8/src/hydrogen-instructions.cc647
-rw-r--r--chromium/v8/src/hydrogen-instructions.h766
-rw-r--r--chromium/v8/src/hydrogen-mark-deoptimize.cc29
-rw-r--r--chromium/v8/src/hydrogen-mark-deoptimize.h12
-rw-r--r--chromium/v8/src/hydrogen-representation-changes.cc10
-rw-r--r--chromium/v8/src/hydrogen-uint32-analysis.cc6
-rw-r--r--chromium/v8/src/hydrogen.cc501
-rw-r--r--chromium/v8/src/hydrogen.h30
-rw-r--r--chromium/v8/src/i18n.cc938
-rw-r--r--chromium/v8/src/i18n.h129
-rw-r--r--chromium/v8/src/ia32/assembler-ia32.cc4
-rw-r--r--chromium/v8/src/ia32/builtins-ia32.cc20
-rw-r--r--chromium/v8/src/ia32/code-stubs-ia32.cc109
-rw-r--r--chromium/v8/src/ia32/codegen-ia32.cc4
-rw-r--r--chromium/v8/src/ia32/debug-ia32.cc2
-rw-r--r--chromium/v8/src/ia32/deoptimizer-ia32.cc2
-rw-r--r--chromium/v8/src/ia32/full-codegen-ia32.cc44
-rw-r--r--chromium/v8/src/ia32/ic-ia32.cc2
-rw-r--r--chromium/v8/src/ia32/lithium-codegen-ia32.cc449
-rw-r--r--chromium/v8/src/ia32/lithium-codegen-ia32.h29
-rw-r--r--chromium/v8/src/ia32/lithium-ia32.cc170
-rw-r--r--chromium/v8/src/ia32/lithium-ia32.h99
-rw-r--r--chromium/v8/src/ia32/macro-assembler-ia32.cc126
-rw-r--r--chromium/v8/src/ia32/macro-assembler-ia32.h21
-rw-r--r--chromium/v8/src/ia32/stub-cache-ia32.cc4
-rw-r--r--chromium/v8/src/ic.cc22
-rw-r--r--chromium/v8/src/ic.h8
-rw-r--r--chromium/v8/src/isolate.cc5
-rw-r--r--chromium/v8/src/isolate.h20
-rw-r--r--chromium/v8/src/lithium.cc4
-rw-r--r--chromium/v8/src/lithium.h48
-rw-r--r--chromium/v8/src/liveedit.cc1
-rw-r--r--chromium/v8/src/log.cc1
-rw-r--r--chromium/v8/src/mark-compact.cc8
-rw-r--r--chromium/v8/src/mark-compact.h2
-rw-r--r--chromium/v8/src/messages.js22
-rw-r--r--chromium/v8/src/mips/assembler-mips.h5
-rw-r--r--chromium/v8/src/mips/builtins-mips.cc20
-rw-r--r--chromium/v8/src/mips/code-stubs-mips.cc58
-rw-r--r--chromium/v8/src/mips/codegen-mips.cc6
-rw-r--r--chromium/v8/src/mips/debug-mips.cc7
-rw-r--r--chromium/v8/src/mips/full-codegen-mips.cc43
-rw-r--r--chromium/v8/src/mips/lithium-codegen-mips.cc285
-rw-r--r--chromium/v8/src/mips/lithium-codegen-mips.h25
-rw-r--r--chromium/v8/src/mips/lithium-gap-resolver-mips.cc2
-rw-r--r--chromium/v8/src/mips/lithium-mips.cc142
-rw-r--r--chromium/v8/src/mips/lithium-mips.h89
-rw-r--r--chromium/v8/src/mips/macro-assembler-mips.cc95
-rw-r--r--chromium/v8/src/mips/macro-assembler-mips.h26
-rw-r--r--chromium/v8/src/object-observe.js5
-rw-r--r--chromium/v8/src/objects-debug.cc9
-rw-r--r--chromium/v8/src/objects-inl.h48
-rw-r--r--chromium/v8/src/objects-printer.cc84
-rw-r--r--chromium/v8/src/objects-visiting.h2
-rw-r--r--chromium/v8/src/objects.cc53
-rw-r--r--chromium/v8/src/objects.h314
-rw-r--r--chromium/v8/src/optimizing-compiler-thread.cc82
-rw-r--r--chromium/v8/src/optimizing-compiler-thread.h11
-rw-r--r--chromium/v8/src/parser.cc14
-rw-r--r--chromium/v8/src/platform-linux.cc3
-rw-r--r--chromium/v8/src/profile-generator-inl.h2
-rw-r--r--chromium/v8/src/profile-generator.cc6
-rw-r--r--chromium/v8/src/profile-generator.h2
-rw-r--r--chromium/v8/src/runtime.cc594
-rw-r--r--chromium/v8/src/runtime.h34
-rw-r--r--chromium/v8/src/runtime.js14
-rw-r--r--chromium/v8/src/sampler.cc11
-rw-r--r--chromium/v8/src/serialize.cc1
-rw-r--r--chromium/v8/src/spaces.h5
-rw-r--r--chromium/v8/src/splay-tree-inl.h9
-rw-r--r--chromium/v8/src/splay-tree.h14
-rw-r--r--chromium/v8/src/type-info.cc12
-rw-r--r--chromium/v8/src/type-info.h1
-rw-r--r--chromium/v8/src/types.h5
-rw-r--r--chromium/v8/src/typing.cc252
-rw-r--r--chromium/v8/src/typing.h17
-rw-r--r--chromium/v8/src/v8.cc5
-rw-r--r--chromium/v8/src/v8globals.h3
-rw-r--r--chromium/v8/src/version.cc4
-rw-r--r--chromium/v8/src/x64/assembler-x64-inl.h5
-rw-r--r--chromium/v8/src/x64/assembler-x64.cc7
-rw-r--r--chromium/v8/src/x64/assembler-x64.h51
-rw-r--r--chromium/v8/src/x64/builtins-x64.cc48
-rw-r--r--chromium/v8/src/x64/code-stubs-x64.cc112
-rw-r--r--chromium/v8/src/x64/codegen-x64.cc4
-rw-r--r--chromium/v8/src/x64/debug-x64.cc7
-rw-r--r--chromium/v8/src/x64/deoptimizer-x64.cc4
-rw-r--r--chromium/v8/src/x64/full-codegen-x64.cc47
-rw-r--r--chromium/v8/src/x64/ic-x64.cc44
-rw-r--r--chromium/v8/src/x64/lithium-codegen-x64.cc396
-rw-r--r--chromium/v8/src/x64/lithium-codegen-x64.h30
-rw-r--r--chromium/v8/src/x64/lithium-x64.cc144
-rw-r--r--chromium/v8/src/x64/lithium-x64.h103
-rw-r--r--chromium/v8/src/x64/macro-assembler-x64.cc94
-rw-r--r--chromium/v8/src/x64/macro-assembler-x64.h14
-rw-r--r--chromium/v8/src/x64/regexp-macro-assembler-x64.cc2
-rw-r--r--chromium/v8/src/x64/stub-cache-x64.cc35
-rw-r--r--chromium/v8/src/zone-inl.h6
-rw-r--r--chromium/v8/src/zone.h11
-rw-r--r--chromium/v8/tools/gcmole/Makefile2
-rwxr-xr-xchromium/v8/tools/gcmole/bootstrap.sh126
-rw-r--r--chromium/v8/tools/gcmole/gcmole.lua3
-rwxr-xr-xchromium/v8/tools/grokdump.py274
-rw-r--r--chromium/v8/tools/gyp/v8.gyp14
-rwxr-xr-xchromium/v8/tools/run-tests.py8
-rw-r--r--chromium/v8/tools/testrunner/local/old_statusfile.py2
-rw-r--r--chromium/v8/tools/testrunner/local/statusfile.py7
-rw-r--r--chromium/v8/tools/testrunner/local/testsuite.py47
-rw-r--r--chromium/v8/tools/testrunner/local/verbose.py2
-rw-r--r--chromium/v8/tools/tickprocessor.js3
-rw-r--r--chromium/v8/tools/v8heapconst.py255
-rw-r--r--chromium/v8/tools/v8heapconst.py.tmpl30
182 files changed, 6760 insertions, 7121 deletions
diff --git a/chromium/v8/ChangeLog b/chromium/v8/ChangeLog
index d824cec0d63..b0ab892073e 100644
--- a/chromium/v8/ChangeLog
+++ b/chromium/v8/ChangeLog
@@ -1,60 +1,3 @@
-2013-08-14: Version 3.20.17
-
- Fixed Math.round/floor that had bogus Smi representation
- (Chromium issue 272564)
-
- Performance and stability improvements on all platforms.
-
-
-2013-08-13: Version 3.20.16
-
- Fixed bug in HPhi::SimplifyConstantInput (Chromium issue 269679)
-
- Fixed gcmole bugs in i18n code (issue 2745)
-
- ia32: Calls to the TranscendentalCacheStub must ensure that esi is
- set (issue 2827)
-
- Made sure polymorphic element access creates non-replaying
- phis. (issue 2815)
-
- Allowed HPhis to have an invalid merge index. (issue 2815)
-
- Fixed smi-based math floor. (Chromium issue 270268)
-
- Deprecated self and total time getters and total sample count
- getter on CpuProfileNode. (Chromium issue 267595)
-
- Fixed Object.freeze, Object.observe wrt CountOperation and
- CompoundAssignment. (issue 2774,2779)
-
- Performance and stability improvements on all platforms.
-
-
-2013-08-07: Version 3.20.14
-
- Exposed eternal handle api.
-
- Bugfix to solve issues with enabling V8 typed arrays in Blink.
-
- Fixed Array index dehoisting. (Chromium issue 264203)
-
- Updated Array Iterator to use numeric indexes (issue 2818)
-
- Return start/end profiling time in microseconds instead of milliseconds
- (issue 2824)
-
- Performance and stability improvements on all platforms.
-
-
-2013-08-06: Version 3.20.14
-
- Added new Harmony methods to Array.prototype object.
- (issue 2776,v8:2777)
-
- Performance and stability improvements on all platforms.
-
-
2013-08-01: Version 3.20.12
Removed buggy ToNumber truncation (partial fix for issue 2813)
diff --git a/chromium/v8/Makefile b/chromium/v8/Makefile
index 288c257396d..499f6cb08e0 100644
--- a/chromium/v8/Makefile
+++ b/chromium/v8/Makefile
@@ -192,7 +192,6 @@ endif
# ----------------- available targets: --------------------
# - "dependencies": pulls in external dependencies (currently: GYP)
-# - "grokdump": rebuilds heap constants lists used by grokdump
# - any arch listed in ARCHES (see below)
# - any mode listed in MODES
# - every combination <arch>.<mode>, e.g. "ia32.release"
@@ -393,7 +392,7 @@ endif
# Replaces the old with the new environment file if they're different, which
# will trigger GYP to regenerate Makefiles.
$(ENVFILE): $(ENVFILE).new
- @if test -r $(ENVFILE) && cmp $(ENVFILE).new $(ENVFILE) > /dev/null; \
+ @if test -r $(ENVFILE) && cmp $(ENVFILE).new $(ENVFILE) >/dev/null; \
then rm $(ENVFILE).new; \
else mv $(ENVFILE).new $(ENVFILE); fi
@@ -402,12 +401,6 @@ $(ENVFILE).new:
@mkdir -p $(OUTDIR); echo "GYPFLAGS=$(GYPFLAGS)" > $(ENVFILE).new; \
echo "CXX=$(CXX)" >> $(ENVFILE).new
-# Heap constants for grokdump.
-DUMP_FILE = tools/v8heapconst.py
-grokdump: ia32.release
- @cat $(DUMP_FILE).tmpl > $(DUMP_FILE)
- @$(OUTDIR)/ia32.release/d8 --dump-heap-constants >> $(DUMP_FILE)
-
# Dependencies.
# Remember to keep these in sync with the DEPS file.
dependencies:
diff --git a/chromium/v8/include/v8-debug.h b/chromium/v8/include/v8-debug.h
index bacccb61ddf..e488aaa8891 100755
--- a/chromium/v8/include/v8-debug.h
+++ b/chromium/v8/include/v8-debug.h
@@ -30,6 +30,40 @@
#include "v8.h"
+#ifdef _WIN32
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t; // NOLINT
+typedef long long int64_t; // NOLINT
+
+// Setup for Windows DLL export/import. See v8.h in this directory for
+// information on how to build/use V8 as a DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+ build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define EXPORT __declspec(dllimport)
+#else
+#define EXPORT
+#endif
+
+#else // _WIN32
+
+// Setup for Linux shared library export. See v8.h in this directory for
+// information on how to build/use V8 as shared library.
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED)
+#define EXPORT __attribute__ ((visibility("default")))
+#else // defined(__GNUC__) && (__GNUC__ >= 4)
+#define EXPORT
+#endif // defined(__GNUC__) && (__GNUC__ >= 4)
+
+#endif // _WIN32
+
+
/**
* Debugger support for the V8 JavaScript engine.
*/
@@ -47,7 +81,7 @@ enum DebugEvent {
};
-class V8_EXPORT Debug {
+class EXPORT Debug {
public:
/**
* A client object passed to the v8 debugger whose ownership will be taken by
diff --git a/chromium/v8/include/v8-preparser.h b/chromium/v8/include/v8-preparser.h
index 1da77185af8..3e39823d65c 100644
--- a/chromium/v8/include/v8-preparser.h
+++ b/chromium/v8/include/v8-preparser.h
@@ -28,14 +28,48 @@
#ifndef PREPARSER_H
#define PREPARSER_H
-#include "v8.h"
#include "v8stdint.h"
+#ifdef _WIN32
+
+// Setup for Windows DLL export/import. When building the V8 DLL the
+// BUILDING_V8_SHARED needs to be defined. When building a program which uses
+// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8
+// static library or building a program which uses the V8 static library neither
+// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+ build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define V8EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define V8EXPORT __declspec(dllimport)
+#else
+#define V8EXPORT
+#endif // BUILDING_V8_SHARED
+
+#else // _WIN32
+
+// Setup for Linux shared library export. There is no need to distinguish
+// between building or using the V8 shared library, but we should not
+// export symbols when we are building a static library.
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || \
+ (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(V8_SHARED)
+#define V8EXPORT __attribute__ ((visibility("default")))
+#else
+#define V8EXPORT
+#endif
+
+#endif // _WIN32
+
+
namespace v8 {
// The result of preparsing is either a stack overflow error, or an opaque
// blob of data that can be passed back into the parser.
-class V8_EXPORT PreParserData {
+class V8EXPORT PreParserData {
public:
PreParserData(size_t size, const uint8_t* data)
: data_(data), size_(size) { }
@@ -60,7 +94,7 @@ class V8_EXPORT PreParserData {
// Interface for a stream of Unicode characters.
-class V8_EXPORT UnicodeInputStream { // NOLINT - V8_EXPORT is not a class name.
+class V8EXPORT UnicodeInputStream { // NOLINT - Thinks V8EXPORT is class name.
public:
virtual ~UnicodeInputStream();
@@ -76,9 +110,11 @@ class V8_EXPORT UnicodeInputStream { // NOLINT - V8_EXPORT is not a class name.
// more stack space than the limit provided, the result's stack_overflow()
// method will return true. Otherwise the result contains preparser
// data that can be used by the V8 parser to speed up parsing.
-PreParserData V8_EXPORT Preparse(UnicodeInputStream* input,
+PreParserData V8EXPORT Preparse(UnicodeInputStream* input,
size_t max_stack_size);
} // namespace v8.
+#undef V8EXPORT
+
#endif // PREPARSER_H
diff --git a/chromium/v8/include/v8-profiler.h b/chromium/v8/include/v8-profiler.h
index e538f4a8406..7898fef1967 100644
--- a/chromium/v8/include/v8-profiler.h
+++ b/chromium/v8/include/v8-profiler.h
@@ -30,6 +30,36 @@
#include "v8.h"
+#ifdef _WIN32
+// Setup for Windows DLL export/import. See v8.h in this directory for
+// information on how to build/use V8 as a DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+ build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define V8EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define V8EXPORT __declspec(dllimport)
+#else
+#define V8EXPORT
+#endif
+
+#else // _WIN32
+
+// Setup for Linux shared library export. See v8.h in this directory for
+// information on how to build/use V8 as shared library.
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || \
+ (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(V8_SHARED)
+#define V8EXPORT __attribute__ ((visibility("default")))
+#else
+#define V8EXPORT
+#endif
+
+#endif // _WIN32
+
+
/**
* Profiler support for the V8 JavaScript engine.
*/
@@ -40,7 +70,7 @@ typedef uint32_t SnapshotObjectId;
/**
* CpuProfileNode represents a node in a call graph.
*/
-class V8_EXPORT CpuProfileNode {
+class V8EXPORT CpuProfileNode {
public:
/** Returns function name (empty string for anonymous functions.) */
Handle<String> GetFunctionName() const;
@@ -61,27 +91,20 @@ class V8_EXPORT CpuProfileNode {
* Returns total (self + children) execution time of the function,
* in milliseconds, estimated by samples count.
*/
- V8_DEPRECATED(double GetTotalTime() const);
+ double GetTotalTime() const;
/**
* Returns self execution time of the function, in milliseconds,
* estimated by samples count.
*/
- V8_DEPRECATED(double GetSelfTime() const);
+ double GetSelfTime() const;
/** Returns the count of samples where function exists. */
- V8_DEPRECATED(double GetTotalSamplesCount() const);
+ double GetTotalSamplesCount() const;
- /** DEPRECATED. Please use GetHitCount instead.
- * Returns the count of samples where function was currently executing.
- */
+ /** Returns the count of samples where function was currently executing. */
double GetSelfSamplesCount() const;
- /**
- * Returns the count of samples where the function was currently executing.
- */
- unsigned GetHitCount() const;
-
/** Returns function entry UID. */
unsigned GetCallUid() const;
@@ -102,7 +125,7 @@ class V8_EXPORT CpuProfileNode {
* CpuProfile contains a CPU profile in a form of top-down call tree
* (from main() down to functions that do all the work).
*/
-class V8_EXPORT CpuProfile {
+class V8EXPORT CpuProfile {
public:
/** Returns CPU profile UID (assigned by the profiler.) */
unsigned GetUid() const;
@@ -153,7 +176,7 @@ class V8_EXPORT CpuProfile {
* Interface for controlling CPU profiling. Instance of the
* profiler can be retrieved using v8::Isolate::GetCpuProfiler.
*/
-class V8_EXPORT CpuProfiler {
+class V8EXPORT CpuProfiler {
public:
/**
* A note on security tokens usage. As scripts from different
@@ -199,11 +222,6 @@ class V8_EXPORT CpuProfiler {
*/
void DeleteAllCpuProfiles();
- /**
- * Tells the profiler whether the embedder is idle.
- */
- void SetIdle(bool is_idle);
-
private:
CpuProfiler();
~CpuProfiler();
@@ -219,7 +237,7 @@ class HeapGraphNode;
* HeapSnapshotEdge represents a directed connection between heap
* graph nodes: from retainers to retained nodes.
*/
-class V8_EXPORT HeapGraphEdge {
+class V8EXPORT HeapGraphEdge {
public:
enum Type {
kContextVariable = 0, // A variable from a function context.
@@ -255,7 +273,7 @@ class V8_EXPORT HeapGraphEdge {
/**
* HeapGraphNode represents a node in a heap graph.
*/
-class V8_EXPORT HeapGraphNode {
+class V8EXPORT HeapGraphNode {
public:
enum Type {
kHidden = 0, // Hidden node, may be filtered when shown to user.
@@ -307,7 +325,7 @@ class V8_EXPORT HeapGraphNode {
/**
* HeapSnapshots record the state of the JS heap at some moment.
*/
-class V8_EXPORT HeapSnapshot {
+class V8EXPORT HeapSnapshot {
public:
enum SerializationFormat {
kJSON = 0 // See format description near 'Serialize' method.
@@ -377,7 +395,7 @@ class RetainedObjectInfo;
* Interface for controlling heap profiling. Instance of the
* profiler can be retrieved using v8::Isolate::GetHeapProfiler.
*/
-class V8_EXPORT HeapProfiler {
+class V8EXPORT HeapProfiler {
public:
/**
* Callback function invoked for obtaining RetainedObjectInfo for
@@ -515,7 +533,7 @@ class V8_EXPORT HeapProfiler {
* keeps them alive only during snapshot collection. Afterwards, they
* are freed by calling the Dispose class function.
*/
-class V8_EXPORT RetainedObjectInfo { // NOLINT
+class V8EXPORT RetainedObjectInfo { // NOLINT
public:
/** Called by V8 when it no longer needs an instance. */
virtual void Dispose() = 0;
@@ -581,4 +599,7 @@ struct HeapStatsUpdate {
} // namespace v8
+#undef V8EXPORT
+
+
#endif // V8_V8_PROFILER_H_
diff --git a/chromium/v8/include/v8-testing.h b/chromium/v8/include/v8-testing.h
index 97b467a91b1..59eebf9db47 100644
--- a/chromium/v8/include/v8-testing.h
+++ b/chromium/v8/include/v8-testing.h
@@ -30,12 +30,42 @@
#include "v8.h"
+#ifdef _WIN32
+// Setup for Windows DLL export/import. See v8.h in this directory for
+// information on how to build/use V8 as a DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+ build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define V8EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define V8EXPORT __declspec(dllimport)
+#else
+#define V8EXPORT
+#endif
+
+#else // _WIN32
+
+// Setup for Linux shared library export. See v8.h in this directory for
+// information on how to build/use V8 as shared library.
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || \
+ (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(V8_SHARED)
+#define V8EXPORT __attribute__ ((visibility("default")))
+#else
+#define V8EXPORT
+#endif
+
+#endif // _WIN32
+
+
/**
* Testing support for the V8 JavaScript engine.
*/
namespace v8 {
-class V8_EXPORT Testing {
+class V8EXPORT Testing {
public:
enum StressType {
kStressTypeOpt,
@@ -69,7 +99,7 @@ class V8_EXPORT Testing {
} // namespace v8
-#undef V8_EXPORT
+#undef V8EXPORT
#endif // V8_V8_TEST_H_
diff --git a/chromium/v8/include/v8.h b/chromium/v8/include/v8.h
index 3252602bcf1..3eb4794f5c6 100644
--- a/chromium/v8/include/v8.h
+++ b/chromium/v8/include/v8.h
@@ -40,9 +40,6 @@
#include "v8stdint.h"
-// We reserve the V8_* prefix for macros defined in V8 public API and
-// assume there are no name conflicts with the embedder's code.
-
#ifdef _WIN32
// Setup for Windows DLL export/import. When building the V8 DLL the
@@ -56,11 +53,11 @@
#endif
#ifdef BUILDING_V8_SHARED
-#define V8_EXPORT __declspec(dllexport)
+#define V8EXPORT __declspec(dllexport)
#elif USING_V8_SHARED
-#define V8_EXPORT __declspec(dllimport)
+#define V8EXPORT __declspec(dllimport)
#else
-#define V8_EXPORT
+#define V8EXPORT
#endif // BUILDING_V8_SHARED
#else // _WIN32
@@ -69,12 +66,12 @@
#if defined(__GNUC__) && ((__GNUC__ >= 4) || \
(__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(V8_SHARED)
#ifdef BUILDING_V8_SHARED
-#define V8_EXPORT __attribute__ ((visibility("default")))
+#define V8EXPORT __attribute__ ((visibility("default")))
#else
-#define V8_EXPORT
+#define V8EXPORT
#endif
#else
-#define V8_EXPORT
+#define V8EXPORT
#endif
#endif // _WIN32
@@ -388,11 +385,6 @@ template <class T> class Handle {
};
-// A value which will never be returned by Local::Eternalize
-// Useful for static initialization
-const int kUninitializedEternalIndex = -1;
-
-
/**
* A light-weight stack-allocated object handle. All operations
* that return objects from within v8 return them in local handles. They
@@ -438,11 +430,6 @@ template <class T> class Local : public Handle<T> {
return Local<S>::Cast(*this);
}
- // Keep this Local alive for the lifetime of the Isolate.
- // It remains retrievable via the returned index,
- V8_INLINE(int Eternalize(Isolate* isolate));
- V8_INLINE(static Local<T> GetEternal(Isolate* isolate, int index));
-
/**
* Create a local handle for the content of another handle.
* The referee is kept alive by the local handle even when
@@ -814,7 +801,7 @@ template <class T> class Persistent // NOLINT
* handle and may deallocate it. The behavior of accessing a handle
* for which the handle scope has been deleted is undefined.
*/
-class V8_EXPORT HandleScope {
+class V8EXPORT HandleScope {
public:
// TODO(svenpanne) Deprecate me when Chrome is fixed!
HandleScope();
@@ -853,7 +840,7 @@ class V8_EXPORT HandleScope {
// This Data class is accessible internally as HandleScopeData through a
// typedef in the ImplementationUtilities class.
- class V8_EXPORT Data {
+ class V8EXPORT Data {
public:
internal::Object** next;
internal::Object** limit;
@@ -886,7 +873,7 @@ class V8_EXPORT HandleScope {
/**
* The superclass of values and API object templates.
*/
-class V8_EXPORT Data {
+class V8EXPORT Data {
private:
Data();
};
@@ -898,7 +885,7 @@ class V8_EXPORT Data {
* compiling it, and can be stored between compilations. When script
* data is given to the compile method compilation will be faster.
*/
-class V8_EXPORT ScriptData { // NOLINT
+class V8EXPORT ScriptData { // NOLINT
public:
virtual ~ScriptData() { }
@@ -976,7 +963,7 @@ class ScriptOrigin {
/**
* A compiled JavaScript script.
*/
-class V8_EXPORT Script {
+class V8EXPORT Script {
public:
/**
* Compiles the specified script (context-independent).
@@ -1094,7 +1081,7 @@ class V8_EXPORT Script {
/**
* An error message.
*/
-class V8_EXPORT Message {
+class V8EXPORT Message {
public:
Local<String> Get() const;
Local<String> GetSourceLine() const;
@@ -1166,7 +1153,7 @@ class V8_EXPORT Message {
* snapshot of the execution stack and the information remains valid after
* execution continues.
*/
-class V8_EXPORT StackTrace {
+class V8EXPORT StackTrace {
public:
/**
* Flags that determine what information is placed captured for each
@@ -1215,7 +1202,7 @@ class V8_EXPORT StackTrace {
/**
* A single JavaScript stack frame.
*/
-class V8_EXPORT StackFrame {
+class V8EXPORT StackFrame {
public:
/**
* Returns the number, 1-based, of the line for the associate function call.
@@ -1267,29 +1254,13 @@ class V8_EXPORT StackFrame {
};
-/**
- * A JSON Parser.
- */
-class V8_EXPORT JSON {
- public:
- /**
- * Tries to parse the string |json_string| and returns it as value if
- * successful.
- *
- * \param json_string The string to parse.
- * \return The corresponding value if successfully parsed.
- */
- static Local<Value> Parse(Local<String> json_string);
-};
-
-
// --- Value ---
/**
* The superclass of all JavaScript values and objects.
*/
-class V8_EXPORT Value : public Data {
+class V8EXPORT Value : public Data {
public:
/**
* Returns true if this value is the undefined value. See ECMA-262
@@ -1520,14 +1491,14 @@ class V8_EXPORT Value : public Data {
/**
* The superclass of primitive values. See ECMA-262 4.3.2.
*/
-class V8_EXPORT Primitive : public Value { };
+class V8EXPORT Primitive : public Value { };
/**
* A primitive boolean value (ECMA-262, 4.3.14). Either the true
* or false value.
*/
-class V8_EXPORT Boolean : public Primitive {
+class V8EXPORT Boolean : public Primitive {
public:
bool Value() const;
V8_INLINE(static Handle<Boolean> New(bool value));
@@ -1537,7 +1508,7 @@ class V8_EXPORT Boolean : public Primitive {
/**
* A JavaScript string value (ECMA-262, 4.3.17).
*/
-class V8_EXPORT String : public Primitive {
+class V8EXPORT String : public Primitive {
public:
enum Encoding {
UNKNOWN_ENCODING = 0x1,
@@ -1643,7 +1614,7 @@ class V8_EXPORT String : public Primitive {
*/
bool IsExternalAscii() const;
- class V8_EXPORT ExternalStringResourceBase { // NOLINT
+ class V8EXPORT ExternalStringResourceBase { // NOLINT
public:
virtual ~ExternalStringResourceBase() {}
@@ -1672,7 +1643,7 @@ class V8_EXPORT String : public Primitive {
* ExternalStringResource to manage the life cycle of the underlying
* buffer. Note that the string data must be immutable.
*/
- class V8_EXPORT ExternalStringResource
+ class V8EXPORT ExternalStringResource
: public ExternalStringResourceBase {
public:
/**
@@ -1706,7 +1677,7 @@ class V8_EXPORT String : public Primitive {
* Use String::New or convert to 16 bit data for non-ASCII.
*/
- class V8_EXPORT ExternalAsciiStringResource
+ class V8EXPORT ExternalAsciiStringResource
: public ExternalStringResourceBase {
public:
/**
@@ -1859,7 +1830,7 @@ class V8_EXPORT String : public Primitive {
* then the length() method returns 0 and the * operator returns
* NULL.
*/
- class V8_EXPORT Utf8Value {
+ class V8EXPORT Utf8Value {
public:
explicit Utf8Value(Handle<v8::Value> obj);
~Utf8Value();
@@ -1882,7 +1853,7 @@ class V8_EXPORT String : public Primitive {
* method of the object) then the length() method returns 0 and the * operator
* returns NULL.
*/
- class V8_EXPORT AsciiValue {
+ class V8EXPORT AsciiValue {
public:
// TODO(dcarney): deprecate
explicit AsciiValue(Handle<v8::Value> obj);
@@ -1905,7 +1876,7 @@ class V8_EXPORT String : public Primitive {
* method of the object) then the length() method returns 0 and the * operator
* returns NULL.
*/
- class V8_EXPORT Value {
+ class V8EXPORT Value {
public:
explicit Value(Handle<v8::Value> obj);
~Value();
@@ -1934,7 +1905,7 @@ class V8_EXPORT String : public Primitive {
*
* This is an experimental feature. Use at your own risk.
*/
-class V8_EXPORT Symbol : public Primitive {
+class V8EXPORT Symbol : public Primitive {
public:
// Returns the print name string of the symbol, or undefined if none.
Local<Value> Name() const;
@@ -1955,7 +1926,7 @@ class V8_EXPORT Symbol : public Primitive {
/**
* A JavaScript number value (ECMA-262, 4.3.20)
*/
-class V8_EXPORT Number : public Primitive {
+class V8EXPORT Number : public Primitive {
public:
double Value() const;
static Local<Number> New(double value);
@@ -1970,7 +1941,7 @@ class V8_EXPORT Number : public Primitive {
/**
* A JavaScript value representing a signed integer.
*/
-class V8_EXPORT Integer : public Number {
+class V8EXPORT Integer : public Number {
public:
static Local<Integer> New(int32_t value);
static Local<Integer> NewFromUnsigned(uint32_t value);
@@ -1987,7 +1958,7 @@ class V8_EXPORT Integer : public Number {
/**
* A JavaScript value representing a 32-bit signed integer.
*/
-class V8_EXPORT Int32 : public Integer {
+class V8EXPORT Int32 : public Integer {
public:
int32_t Value() const;
private:
@@ -1998,7 +1969,7 @@ class V8_EXPORT Int32 : public Integer {
/**
* A JavaScript value representing a 32-bit unsigned integer.
*/
-class V8_EXPORT Uint32 : public Integer {
+class V8EXPORT Uint32 : public Integer {
public:
uint32_t Value() const;
private:
@@ -2070,7 +2041,7 @@ enum AccessControl {
/**
* A JavaScript object (ECMA-262, 4.3.3)
*/
-class V8_EXPORT Object : public Value {
+class V8EXPORT Object : public Value {
public:
bool Set(Handle<Value> key,
Handle<Value> value,
@@ -2342,7 +2313,7 @@ class V8_EXPORT Object : public Value {
/**
* An instance of the built-in array constructor (ECMA-262, 15.4.2).
*/
-class V8_EXPORT Array : public Object {
+class V8EXPORT Array : public Object {
public:
uint32_t Length() const;
@@ -2368,7 +2339,7 @@ class V8_EXPORT Array : public Object {
/**
* A JavaScript function object (ECMA-262, 15.3).
*/
-class V8_EXPORT Function : public Object {
+class V8EXPORT Function : public Object {
public:
Local<Object> NewInstance() const;
Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
@@ -2424,7 +2395,7 @@ class V8_EXPORT Function : public Object {
* An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT ArrayBuffer : public Object {
+class V8EXPORT ArrayBuffer : public Object {
public:
/**
* Allocator that V8 uses to allocate |ArrayBuffer|'s memory.
@@ -2433,7 +2404,7 @@ class V8_EXPORT ArrayBuffer : public Object {
*
* This API is experimental and may change significantly.
*/
- class V8_EXPORT Allocator { // NOLINT
+ class V8EXPORT Allocator { // NOLINT
public:
virtual ~Allocator() {}
@@ -2480,7 +2451,7 @@ class V8_EXPORT ArrayBuffer : public Object {
*
* This API is experimental and may change significantly.
*/
- class V8_EXPORT Contents { // NOLINT
+ class V8EXPORT Contents { // NOLINT
public:
Contents() : data_(NULL), byte_length_(0) {}
@@ -2563,7 +2534,7 @@ class V8_EXPORT ArrayBuffer : public Object {
*
* This API is experimental and may change significantly.
*/
-class V8_EXPORT ArrayBufferView : public Object {
+class V8EXPORT ArrayBufferView : public Object {
public:
/**
* Returns underlying ArrayBuffer.
@@ -2598,7 +2569,7 @@ class V8_EXPORT ArrayBufferView : public Object {
* (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT TypedArray : public ArrayBufferView {
+class V8EXPORT TypedArray : public ArrayBufferView {
public:
/**
* Number of elements in this typed array
@@ -2618,7 +2589,7 @@ class V8_EXPORT TypedArray : public ArrayBufferView {
* An instance of Uint8Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Uint8Array : public TypedArray {
+class V8EXPORT Uint8Array : public TypedArray {
public:
static Local<Uint8Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2634,7 +2605,7 @@ class V8_EXPORT Uint8Array : public TypedArray {
* An instance of Uint8ClampedArray constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Uint8ClampedArray : public TypedArray {
+class V8EXPORT Uint8ClampedArray : public TypedArray {
public:
static Local<Uint8ClampedArray> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2649,7 +2620,7 @@ class V8_EXPORT Uint8ClampedArray : public TypedArray {
* An instance of Int8Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Int8Array : public TypedArray {
+class V8EXPORT Int8Array : public TypedArray {
public:
static Local<Int8Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2665,7 +2636,7 @@ class V8_EXPORT Int8Array : public TypedArray {
* An instance of Uint16Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Uint16Array : public TypedArray {
+class V8EXPORT Uint16Array : public TypedArray {
public:
static Local<Uint16Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2681,7 +2652,7 @@ class V8_EXPORT Uint16Array : public TypedArray {
* An instance of Int16Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Int16Array : public TypedArray {
+class V8EXPORT Int16Array : public TypedArray {
public:
static Local<Int16Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2697,7 +2668,7 @@ class V8_EXPORT Int16Array : public TypedArray {
* An instance of Uint32Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Uint32Array : public TypedArray {
+class V8EXPORT Uint32Array : public TypedArray {
public:
static Local<Uint32Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2713,7 +2684,7 @@ class V8_EXPORT Uint32Array : public TypedArray {
* An instance of Int32Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Int32Array : public TypedArray {
+class V8EXPORT Int32Array : public TypedArray {
public:
static Local<Int32Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2729,7 +2700,7 @@ class V8_EXPORT Int32Array : public TypedArray {
* An instance of Float32Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Float32Array : public TypedArray {
+class V8EXPORT Float32Array : public TypedArray {
public:
static Local<Float32Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2745,7 +2716,7 @@ class V8_EXPORT Float32Array : public TypedArray {
* An instance of Float64Array constructor (ES6 draft 15.13.6).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT Float64Array : public TypedArray {
+class V8EXPORT Float64Array : public TypedArray {
public:
static Local<Float64Array> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2761,7 +2732,7 @@ class V8_EXPORT Float64Array : public TypedArray {
* An instance of DataView constructor (ES6 draft 15.13.7).
* This API is experimental and may change significantly.
*/
-class V8_EXPORT DataView : public ArrayBufferView {
+class V8EXPORT DataView : public ArrayBufferView {
public:
static Local<DataView> New(Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);
@@ -2776,7 +2747,7 @@ class V8_EXPORT DataView : public ArrayBufferView {
/**
* An instance of the built-in Date constructor (ECMA-262, 15.9).
*/
-class V8_EXPORT Date : public Object {
+class V8EXPORT Date : public Object {
public:
static Local<Value> New(double time);
@@ -2814,7 +2785,7 @@ class V8_EXPORT Date : public Object {
/**
* A Number object (ECMA-262, 4.3.21).
*/
-class V8_EXPORT NumberObject : public Object {
+class V8EXPORT NumberObject : public Object {
public:
static Local<Value> New(double value);
@@ -2837,7 +2808,7 @@ class V8_EXPORT NumberObject : public Object {
/**
* A Boolean object (ECMA-262, 4.3.15).
*/
-class V8_EXPORT BooleanObject : public Object {
+class V8EXPORT BooleanObject : public Object {
public:
static Local<Value> New(bool value);
@@ -2860,7 +2831,7 @@ class V8_EXPORT BooleanObject : public Object {
/**
* A String object (ECMA-262, 4.3.18).
*/
-class V8_EXPORT StringObject : public Object {
+class V8EXPORT StringObject : public Object {
public:
static Local<Value> New(Handle<String> value);
@@ -2885,7 +2856,7 @@ class V8_EXPORT StringObject : public Object {
*
* This is an experimental feature. Use at your own risk.
*/
-class V8_EXPORT SymbolObject : public Object {
+class V8EXPORT SymbolObject : public Object {
public:
static Local<Value> New(Isolate* isolate, Handle<Symbol> value);
@@ -2908,7 +2879,7 @@ class V8_EXPORT SymbolObject : public Object {
/**
* An instance of the built-in RegExp constructor (ECMA-262, 15.10).
*/
-class V8_EXPORT RegExp : public Object {
+class V8EXPORT RegExp : public Object {
public:
/**
* Regular expression flag bits. They can be or'ed to enable a set
@@ -2955,7 +2926,7 @@ class V8_EXPORT RegExp : public Object {
* A JavaScript value that wraps a C++ void*. This type of value is mainly used
* to associate C++ data structures with JavaScript objects.
*/
-class V8_EXPORT External : public Value {
+class V8EXPORT External : public Value {
public:
static Local<External> New(void* value);
V8_INLINE(static External* Cast(Value* obj));
@@ -2971,7 +2942,7 @@ class V8_EXPORT External : public Value {
/**
* The superclass of object and function templates.
*/
-class V8_EXPORT Template : public Data {
+class V8EXPORT Template : public Data {
public:
/** Adds a property to each instance created by this template.*/
void Set(Handle<String> name, Handle<Data> value,
@@ -3059,7 +3030,7 @@ class FunctionCallbackInfo {
};
-class V8_EXPORT Arguments : public FunctionCallbackInfo<Value> {
+class V8EXPORT Arguments : public FunctionCallbackInfo<Value> {
private:
friend class internal::FunctionCallbackArguments;
V8_INLINE(Arguments(internal::Object** implicit_args,
@@ -3100,7 +3071,7 @@ class PropertyCallbackInfo {
};
-class V8_EXPORT AccessorInfo : public PropertyCallbackInfo<Value> {
+class V8EXPORT AccessorInfo : public PropertyCallbackInfo<Value> {
private:
friend class internal::PropertyCallbackArguments;
V8_INLINE(AccessorInfo(internal::Object** args))
@@ -3348,7 +3319,7 @@ typedef bool (*IndexedSecurityCallback)(Local<Object> host,
* child_instance.instance_property == 3;
* \endcode
*/
-class V8_EXPORT FunctionTemplate : public Template {
+class V8EXPORT FunctionTemplate : public Template {
public:
/** Creates a function template.*/
V8_DEPRECATED(static Local<FunctionTemplate> New(
@@ -3439,7 +3410,7 @@ class V8_EXPORT FunctionTemplate : public Template {
* Properties added to an ObjectTemplate are added to each object
* created from the ObjectTemplate.
*/
-class V8_EXPORT ObjectTemplate : public Template {
+class V8EXPORT ObjectTemplate : public Template {
public:
/** Creates an ObjectTemplate. */
static Local<ObjectTemplate> New();
@@ -3625,7 +3596,7 @@ class V8_EXPORT ObjectTemplate : public Template {
* A Signature specifies which receivers and arguments are valid
* parameters to a function.
*/
-class V8_EXPORT Signature : public Data {
+class V8EXPORT Signature : public Data {
public:
static Local<Signature> New(Handle<FunctionTemplate> receiver =
Handle<FunctionTemplate>(),
@@ -3640,7 +3611,7 @@ class V8_EXPORT Signature : public Data {
* An AccessorSignature specifies which receivers are valid parameters
* to an accessor callback.
*/
-class V8_EXPORT AccessorSignature : public Data {
+class V8EXPORT AccessorSignature : public Data {
public:
static Local<AccessorSignature> New(Handle<FunctionTemplate> receiver =
Handle<FunctionTemplate>());
@@ -3649,13 +3620,13 @@ class V8_EXPORT AccessorSignature : public Data {
};
-class V8_EXPORT DeclaredAccessorDescriptor : public Data {
+class V8EXPORT DeclaredAccessorDescriptor : public Data {
private:
DeclaredAccessorDescriptor();
};
-class V8_EXPORT ObjectOperationDescriptor : public Data {
+class V8EXPORT ObjectOperationDescriptor : public Data {
public:
// This function is not yet stable and should not be used at this time.
static Local<RawOperationDescriptor> NewInternalFieldDereference(
@@ -3675,7 +3646,7 @@ enum DeclaredAccessorDescriptorDataType {
};
-class V8_EXPORT RawOperationDescriptor : public Data {
+class V8EXPORT RawOperationDescriptor : public Data {
public:
Local<DeclaredAccessorDescriptor> NewHandleDereference(Isolate* isolate);
Local<RawOperationDescriptor> NewRawDereference(Isolate* isolate);
@@ -3708,7 +3679,7 @@ class V8_EXPORT RawOperationDescriptor : public Data {
* A utility for determining the type of objects based on the template
* they were constructed from.
*/
-class V8_EXPORT TypeSwitch : public Data {
+class V8EXPORT TypeSwitch : public Data {
public:
static Local<TypeSwitch> New(Handle<FunctionTemplate> type);
static Local<TypeSwitch> New(int argc, Handle<FunctionTemplate> types[]);
@@ -3720,7 +3691,7 @@ class V8_EXPORT TypeSwitch : public Data {
// --- Extensions ---
-class V8_EXPORT ExternalAsciiStringResourceImpl
+class V8EXPORT ExternalAsciiStringResourceImpl
: public String::ExternalAsciiStringResource {
public:
ExternalAsciiStringResourceImpl() : data_(0), length_(0) {}
@@ -3737,7 +3708,7 @@ class V8_EXPORT ExternalAsciiStringResourceImpl
/**
* Ignore
*/
-class V8_EXPORT Extension { // NOLINT
+class V8EXPORT Extension { // NOLINT
public:
// Note that the strings passed into this constructor must live as long
// as the Extension itself.
@@ -3775,13 +3746,13 @@ class V8_EXPORT Extension { // NOLINT
};
-void V8_EXPORT RegisterExtension(Extension* extension);
+void V8EXPORT RegisterExtension(Extension* extension);
/**
* Ignore
*/
-class V8_EXPORT DeclareExtension {
+class V8EXPORT DeclareExtension {
public:
V8_INLINE(DeclareExtension(Extension* extension)) {
RegisterExtension(extension);
@@ -3792,10 +3763,10 @@ class V8_EXPORT DeclareExtension {
// --- Statics ---
-Handle<Primitive> V8_EXPORT Undefined();
-Handle<Primitive> V8_EXPORT Null();
-Handle<Boolean> V8_EXPORT True();
-Handle<Boolean> V8_EXPORT False();
+Handle<Primitive> V8EXPORT Undefined();
+Handle<Primitive> V8EXPORT Null();
+Handle<Boolean> V8EXPORT True();
+Handle<Boolean> V8EXPORT False();
V8_INLINE(Handle<Primitive> Undefined(Isolate* isolate));
V8_INLINE(Handle<Primitive> Null(Isolate* isolate));
@@ -3812,7 +3783,7 @@ V8_INLINE(Handle<Boolean> False(Isolate* isolate));
* setting the stack limit and you must set a non-default stack limit separately
* for each thread.
*/
-class V8_EXPORT ResourceConstraints {
+class V8EXPORT ResourceConstraints {
public:
ResourceConstraints();
int max_young_space_size() const { return max_young_space_size_; }
@@ -3832,7 +3803,7 @@ class V8_EXPORT ResourceConstraints {
};
-bool V8_EXPORT SetResourceConstraints(ResourceConstraints* constraints);
+bool V8EXPORT SetResourceConstraints(ResourceConstraints* constraints);
// --- Exceptions ---
@@ -3850,13 +3821,13 @@ typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> error);
* operation; the caller must return immediately and only after the exception
* has been handled does it become legal to invoke JavaScript operations.
*/
-Handle<Value> V8_EXPORT ThrowException(Handle<Value> exception);
+Handle<Value> V8EXPORT ThrowException(Handle<Value> exception);
/**
* Create new error objects by calling the corresponding error object
* constructor with the message.
*/
-class V8_EXPORT Exception {
+class V8EXPORT Exception {
public:
static Local<Value> RangeError(Handle<String> message);
static Local<Value> ReferenceError(Handle<String> message);
@@ -3950,7 +3921,7 @@ typedef void (*GCCallback)();
* Instances of this class can be passed to v8::V8::HeapStatistics to
* get heap statistics from V8.
*/
-class V8_EXPORT HeapStatistics {
+class V8EXPORT HeapStatistics {
public:
HeapStatistics();
size_t total_heap_size() { return total_heap_size_; }
@@ -3982,13 +3953,13 @@ class RetainedObjectInfo;
* threads. An isolate can be entered by at most one thread at any
* given time. The Locker/Unlocker API must be used to synchronize.
*/
-class V8_EXPORT Isolate {
+class V8EXPORT Isolate {
public:
/**
* Stack-allocated class which sets the isolate for all operations
* executed within a local scope.
*/
- class V8_EXPORT Scope {
+ class V8EXPORT Scope {
public:
explicit Scope(Isolate* isolate) : isolate_(isolate) {
isolate->Enter();
@@ -4136,7 +4107,7 @@ class V8_EXPORT Isolate {
};
-class V8_EXPORT StartupData {
+class V8EXPORT StartupData {
public:
enum CompressionAlgorithm {
kUncompressed,
@@ -4157,7 +4128,7 @@ class V8_EXPORT StartupData {
*
* For an example of the class usage, see the "shell.cc" sample application.
*/
-class V8_EXPORT StartupDataDecompressor { // NOLINT
+class V8EXPORT StartupDataDecompressor { // NOLINT
public:
StartupDataDecompressor();
virtual ~StartupDataDecompressor();
@@ -4301,7 +4272,7 @@ typedef void (*JitCodeEventHandler)(const JitCodeEvent* event);
/**
* Interface for iterating through all external resources in the heap.
*/
-class V8_EXPORT ExternalResourceVisitor { // NOLINT
+class V8EXPORT ExternalResourceVisitor { // NOLINT
public:
virtual ~ExternalResourceVisitor() {}
virtual void VisitExternalString(Handle<String> string) {}
@@ -4311,7 +4282,7 @@ class V8_EXPORT ExternalResourceVisitor { // NOLINT
/**
* Interface for iterating through all the persistent handles in the heap.
*/
-class V8_EXPORT PersistentHandleVisitor { // NOLINT
+class V8EXPORT PersistentHandleVisitor { // NOLINT
public:
virtual ~PersistentHandleVisitor() {}
virtual void VisitPersistentHandle(Persistent<Value>* value,
@@ -4324,7 +4295,7 @@ class V8_EXPORT PersistentHandleVisitor { // NOLINT
* to be modified. Useful when otherwise unsafe handle operations need to
* be performed.
*/
-class V8_EXPORT AssertNoGCScope {
+class V8EXPORT AssertNoGCScope {
#ifndef DEBUG
// TODO(yangguo): remove isolate argument.
V8_INLINE(AssertNoGCScope(Isolate* isolate)) { }
@@ -4340,7 +4311,7 @@ class V8_EXPORT AssertNoGCScope {
/**
* Container class for static utility functions.
*/
-class V8_EXPORT V8 {
+class V8EXPORT V8 {
public:
/** Set the callback to invoke in case of fatal errors. */
static void SetFatalErrorHandler(FatalErrorCallback that);
@@ -4797,9 +4768,6 @@ class V8_EXPORT V8 {
void* data,
RevivableCallback weak_reference_callback);
static void ClearWeak(internal::Object** global_handle);
- static int Eternalize(internal::Isolate* isolate,
- internal::Object** handle);
- static internal::Object** GetEternal(internal::Isolate* isolate, int index);
template <class T> friend class Handle;
template <class T> friend class Local;
@@ -4811,7 +4779,7 @@ class V8_EXPORT V8 {
/**
* An external exception handler.
*/
-class V8_EXPORT TryCatch {
+class V8EXPORT TryCatch {
public:
/**
* Creates a new try/catch block and registers it with v8. Note that
@@ -4944,7 +4912,7 @@ class V8_EXPORT TryCatch {
/**
* Ignore
*/
-class V8_EXPORT ExtensionConfiguration {
+class V8EXPORT ExtensionConfiguration {
public:
ExtensionConfiguration(int name_count, const char* names[])
: name_count_(name_count), names_(names) { }
@@ -4959,7 +4927,7 @@ class V8_EXPORT ExtensionConfiguration {
* A sandboxed execution context with its own set of built-in objects
* and functions.
*/
-class V8_EXPORT Context {
+class V8EXPORT Context {
public:
/**
* Returns the global proxy object or global object itself for
@@ -5244,7 +5212,7 @@ class V8_EXPORT Context {
* // V8 Now no longer locked.
* \endcode
*/
-class V8_EXPORT Unlocker {
+class V8EXPORT Unlocker {
public:
/**
* Initialize Unlocker for a given Isolate.
@@ -5262,7 +5230,7 @@ class V8_EXPORT Unlocker {
};
-class V8_EXPORT Locker {
+class V8EXPORT Locker {
public:
/**
* Initialize Locker for a given Isolate.
@@ -5323,7 +5291,7 @@ struct HeapStatsUpdate;
/**
* An interface for exporting data from V8, using "push" model.
*/
-class V8_EXPORT OutputStream { // NOLINT
+class V8EXPORT OutputStream { // NOLINT
public:
enum OutputEncoding {
kAscii = 0 // 7-bit ASCII.
@@ -5360,7 +5328,7 @@ class V8_EXPORT OutputStream { // NOLINT
* An interface for reporting progress and controlling long-running
* activities.
*/
-class V8_EXPORT ActivityControl { // NOLINT
+class V8EXPORT ActivityControl { // NOLINT
public:
enum ControlOption {
kContinue = 0,
@@ -5483,7 +5451,7 @@ class Internals {
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
- static const int kEmptyStringRootIndex = 133;
+ static const int kEmptyStringRootIndex = 135;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@@ -5544,14 +5512,14 @@ class Internals {
V8_INLINE(static uint8_t GetNodeFlag(internal::Object** obj, int shift)) {
uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
- return *addr & static_cast<uint8_t>(1U << shift);
+ return *addr & (1 << shift);
}
V8_INLINE(static void UpdateNodeFlag(internal::Object** obj,
bool value, int shift)) {
uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
- uint8_t mask = static_cast<uint8_t>(1 << shift);
- *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
+ uint8_t mask = 1 << shift;
+ *addr = (*addr & ~mask) | (value << shift);
}
V8_INLINE(static uint8_t GetNodeState(internal::Object** obj)) {
@@ -5562,7 +5530,7 @@ class Internals {
V8_INLINE(static void UpdateNodeState(internal::Object** obj,
uint8_t value)) {
uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
- *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
+ *addr = (*addr & ~kNodeStateMask) | value;
}
V8_INLINE(static void SetEmbedderData(v8::Isolate* isolate, void* data)) {
@@ -5663,21 +5631,6 @@ Local<T> Local<T>::New(Isolate* isolate, T* that) {
}
-template<class T>
-int Local<T>::Eternalize(Isolate* isolate) {
- return V8::Eternalize(reinterpret_cast<internal::Isolate*>(isolate),
- reinterpret_cast<internal::Object**>(this->val_));
-}
-
-
-template<class T>
-Local<T> Local<T>::GetEternal(Isolate* isolate, int index) {
- internal::Object** handle =
- V8::GetEternal(reinterpret_cast<internal::Isolate*>(isolate), index);
- return Local<T>(T::Cast(reinterpret_cast<Value*>(handle)));
-}
-
-
#ifdef V8_USE_UNSAFE_HANDLES
template <class T>
Persistent<T> Persistent<T>::New(Handle<T> that) {
@@ -5927,7 +5880,7 @@ void ReturnValue<T>::Set(uint32_t i) {
TYPE_CHECK(T, Integer);
typedef internal::Internals I;
// Can't simply use INT32_MAX here for whatever reason.
- bool fits_into_int32_t = (i & (1U << 31)) == 0;
+ bool fits_into_int32_t = (i & (1 << 31)) == 0;
if (V8_LIKELY(fits_into_int32_t)) {
Set(static_cast<int32_t>(i));
return;
@@ -6589,6 +6542,7 @@ void* Context::GetAlignedPointerFromEmbedderData(int index) {
} // namespace v8
+#undef V8EXPORT
#undef TYPE_CHECK
diff --git a/chromium/v8/src/api.cc b/chromium/v8/src/api.cc
index eb2ffcff180..7b2524cc4d7 100644
--- a/chromium/v8/src/api.cc
+++ b/chromium/v8/src/api.cc
@@ -46,7 +46,6 @@
#include "heap-profiler.h"
#include "heap-snapshot-generator-inl.h"
#include "icu_util.h"
-#include "json-parser.h"
#include "messages.h"
#ifdef COMPRESS_STARTUP_DATA_BZ2
#include "natives.h"
@@ -676,16 +675,6 @@ void V8::DisposeGlobal(i::Object** obj) {
}
-int V8::Eternalize(i::Isolate* isolate, i::Object** handle) {
- return isolate->eternal_handles()->Create(isolate, *handle);
-}
-
-
-i::Object** V8::GetEternal(i::Isolate* isolate, int index) {
- return isolate->eternal_handles()->Get(index).location();
-}
-
-
// --- H a n d l e s ---
@@ -781,6 +770,7 @@ void Context::Exit() {
i::Context* last_context =
isolate->handle_scope_implementer()->RestoreContext();
isolate->set_context(last_context);
+ isolate->set_context_exit_happened(true);
}
@@ -2617,29 +2607,6 @@ bool StackFrame::IsConstructor() const {
}
-// --- J S O N ---
-
-Local<Value> JSON::Parse(Local<String> json_string) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::JSON::Parse");
- ENTER_V8(isolate);
- i::HandleScope scope(isolate);
- i::Handle<i::String> source = i::Handle<i::String>(
- FlattenGetString(Utils::OpenHandle(*json_string)));
- EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> result;
- if (source->IsSeqOneByteString()) {
- result = i::JsonParser<true>::Parse(source);
- } else {
- result = i::JsonParser<false>::Parse(source);
- }
- has_pending_exception = result.is_null();
- EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
- return Utils::ToLocal(
- i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
-}
-
-
// --- D a t a ---
bool Value::FullIsUndefined() const {
@@ -7477,6 +7444,8 @@ Handle<String> CpuProfileNode::GetFunctionName() const {
int CpuProfileNode::GetScriptId() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptId");
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
const i::CodeEntry* entry = node->entry();
return entry->script_id();
@@ -7493,6 +7462,8 @@ Handle<String> CpuProfileNode::GetScriptResourceName() const {
int CpuProfileNode::GetLineNumber() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetLineNumber");
return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
}
@@ -7525,12 +7496,9 @@ double CpuProfileNode::GetSelfSamplesCount() const {
}
-unsigned CpuProfileNode::GetHitCount() const {
- return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
-}
-
-
unsigned CpuProfileNode::GetCallUid() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetCallUid");
return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
}
@@ -7541,11 +7509,15 @@ unsigned CpuProfileNode::GetNodeId() const {
int CpuProfileNode::GetChildrenCount() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount");
return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
}
const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetChild");
const i::ProfileNode* child =
reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
return reinterpret_cast<const CpuProfileNode*>(child);
@@ -7566,6 +7538,8 @@ void CpuProfile::Delete() {
unsigned CpuProfile::GetUid() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfile::GetUid");
return reinterpret_cast<const i::CpuProfile*>(this)->uid();
}
@@ -7580,6 +7554,8 @@ Handle<String> CpuProfile::GetTitle() const {
const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfile::GetTopDownRoot");
const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
}
@@ -7637,19 +7613,6 @@ void CpuProfiler::DeleteAllCpuProfiles() {
}
-void CpuProfiler::SetIdle(bool is_idle) {
- i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
- i::StateTag state = isolate->current_vm_state();
- ASSERT(state == i::EXTERNAL || state == i::IDLE);
- if (isolate->js_entry_sp() != NULL) return;
- if (is_idle) {
- isolate->set_current_vm_state(i::IDLE);
- } else if (state == i::IDLE) {
- isolate->set_current_vm_state(i::EXTERNAL);
- }
-}
-
-
static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
return const_cast<i::HeapGraphEdge*>(
reinterpret_cast<const i::HeapGraphEdge*>(edge));
diff --git a/chromium/v8/src/arm/builtins-arm.cc b/chromium/v8/src/arm/builtins-arm.cc
index 5f3a999f561..eff47e2692b 100644
--- a/chromium/v8/src/arm/builtins-arm.cc
+++ b/chromium/v8/src/arm/builtins-arm.cc
@@ -119,9 +119,9 @@ void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
// Initial map for the builtin InternalArray functions should be maps.
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
__ SmiTst(r2);
- __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction);
+ __ Assert(ne, "Unexpected initial map for InternalArray function");
__ CompareObjectType(r2, r3, r4, MAP_TYPE);
- __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction);
+ __ Assert(eq, "Unexpected initial map for InternalArray function");
}
// Run the native code for the InternalArray function called as a normal
@@ -147,9 +147,9 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
// Initial map for the builtin Array functions should be maps.
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
__ SmiTst(r2);
- __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(ne, "Unexpected initial map for Array function");
__ CompareObjectType(r2, r3, r4, MAP_TYPE);
- __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(eq, "Unexpected initial map for Array function");
}
// Run the native code for the Array function called as a normal function.
@@ -178,7 +178,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
__ cmp(function, Operand(r2));
- __ Assert(eq, kUnexpectedStringFunction);
+ __ Assert(eq, "Unexpected String function");
}
// Load the first arguments in r0 and get rid of the rest.
@@ -224,10 +224,10 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
__ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
- __ Assert(eq, kUnexpectedStringWrapperInstanceSize);
+ __ Assert(eq, "Unexpected string wrapper instance size");
__ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
__ cmp(r4, Operand::Zero());
- __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper);
+ __ Assert(eq, "Unexpected unused properties of string wrapper");
}
__ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
@@ -471,7 +471,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// r0: offset of first field after pre-allocated fields
if (FLAG_debug_code) {
__ cmp(r0, r6);
- __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
+ __ Assert(le, "Unexpected number of pre-allocated property fields.");
}
__ InitializeFieldsWithFiller(r5, r0, r7);
// To allow for truncation.
@@ -503,7 +503,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Done if no extra properties are to be allocated.
__ b(eq, &allocated);
- __ Assert(pl, kPropertyAllocationCountFailed);
+ __ Assert(pl, "Property allocation count failed.");
// Scale the number of elements by pointer size and add the header for
// FixedArrays to the start of the next object calculation from above.
@@ -547,7 +547,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
} else if (FLAG_debug_code) {
__ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
__ cmp(r7, r8);
- __ Assert(eq, kUndefinedValueNotLoaded);
+ __ Assert(eq, "Undefined value not loaded.");
}
__ b(&entry);
__ bind(&loop);
diff --git a/chromium/v8/src/arm/code-stubs-arm.cc b/chromium/v8/src/arm/code-stubs-arm.cc
index 98a835fd1a5..ba98b963153 100644
--- a/chromium/v8/src/arm/code-stubs-arm.cc
+++ b/chromium/v8/src/arm/code-stubs-arm.cc
@@ -246,6 +246,17 @@ void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
}
+void UnaryOpStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { r0 };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
void StoreGlobalStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -509,8 +520,9 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
Label after_sentinel;
__ JumpIfNotSmi(r3, &after_sentinel);
if (FLAG_debug_code) {
+ const char* message = "Expected 0 as a Smi sentinel";
__ cmp(r3, Operand::Zero());
- __ Assert(eq, kExpected0AsASmiSentinel);
+ __ Assert(eq, message);
}
__ ldr(r3, GlobalObjectOperand());
__ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
@@ -3905,9 +3917,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
if (FLAG_debug_code) {
__ SmiTst(regexp_data);
- __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected);
+ __ Check(ne, "Unexpected type for RegExp data, FixedArray expected");
__ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
- __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
+ __ Check(eq, "Unexpected type for RegExp data, FixedArray expected");
}
// regexp_data: RegExp data (FixedArray)
@@ -4249,7 +4261,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ tst(r0, Operand(kIsIndirectStringMask));
- __ Assert(eq, kExternalStringExpectedButNotFound);
+ __ Assert(eq, "external string expected, but not found");
}
__ ldr(subject,
FieldMemOperand(subject, ExternalString::kResourceDataOffset));
@@ -4631,7 +4643,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharCodeAtGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough to CharCodeAt slow case");
// Index is not a smi.
__ bind(&index_not_smi_);
@@ -4676,7 +4688,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough from CharCodeAt slow case");
}
@@ -4706,7 +4718,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough to CharFromCode slow case");
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
@@ -4716,7 +4728,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough from CharFromCode slow case");
}
@@ -4773,7 +4785,7 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
// Check that destination is actually word aligned if the flag says
// that it is.
__ tst(dest, Operand(kPointerAlignmentMask));
- __ Check(eq, kDestinationOfCopyNotAligned);
+ __ Check(eq, "Destination of copy not aligned.");
}
const int kReadAlignment = 4;
@@ -5002,7 +5014,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
if (FLAG_debug_code) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(ip, candidate);
- __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole);
+ __ Assert(eq, "oddball in string table is not undefined or the hole");
}
__ jmp(&next_probe[i]);
@@ -6900,7 +6912,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -6957,7 +6969,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -7018,9 +7030,9 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ tst(r3, Operand(kSmiTagMask));
- __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(ne, "Unexpected initial map for Array function");
__ CompareObjectType(r3, r3, r4, MAP_TYPE);
- __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(eq, "Unexpected initial map for Array function");
// We should either have undefined in ebx or a valid cell
Label okay_here;
@@ -7029,7 +7041,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ b(eq, &okay_here);
__ ldr(r3, FieldMemOperand(r2, 0));
__ cmp(r3, Operand(cell_map));
- __ Assert(eq, kExpectedPropertyCellInRegisterEbx);
+ __ Assert(eq, "Expected property cell in register ebx");
__ bind(&okay_here);
}
@@ -7132,9 +7144,9 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
__ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ tst(r3, Operand(kSmiTagMask));
- __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(ne, "Unexpected initial map for Array function");
__ CompareObjectType(r3, r3, r4, MAP_TYPE);
- __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(eq, "Unexpected initial map for Array function");
}
// Figure out the right elements kind
@@ -7151,7 +7163,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
__ b(eq, &done);
__ cmp(r3, Operand(FAST_HOLEY_ELEMENTS));
__ Assert(eq,
- kInvalidElementsKindForInternalArrayOrInternalPackedArray);
+ "Invalid ElementsKind for InternalArray or InternalPackedArray");
__ bind(&done);
}
diff --git a/chromium/v8/src/arm/codegen-arm.cc b/chromium/v8/src/arm/codegen-arm.cc
index 1bcf3e3a605..7559373ee9a 100644
--- a/chromium/v8/src/arm/codegen-arm.cc
+++ b/chromium/v8/src/arm/codegen-arm.cc
@@ -532,7 +532,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
__ SmiTag(r9);
__ orr(r9, r9, Operand(1));
__ CompareRoot(r9, Heap::kTheHoleValueRootIndex);
- __ Assert(eq, kObjectFoundInSmiOnlyArray);
+ __ Assert(eq, "object found in smi-only array");
}
__ Strd(r4, r5, MemOperand(r7, 8, PostIndex));
@@ -728,7 +728,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ tst(result, Operand(kIsIndirectStringMask));
- __ Assert(eq, kExternalStringExpectedButNotFound);
+ __ Assert(eq, "external string expected, but not found");
}
// Rule out short external strings.
STATIC_CHECK(kShortExternalStringTag != 0);
diff --git a/chromium/v8/src/arm/debug-arm.cc b/chromium/v8/src/arm/debug-arm.cc
index 108435f0a9f..7faea08034b 100644
--- a/chromium/v8/src/arm/debug-arm.cc
+++ b/chromium/v8/src/arm/debug-arm.cc
@@ -130,7 +130,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
if ((non_object_regs & (1 << r)) != 0) {
if (FLAG_debug_code) {
__ tst(reg, Operand(0xc0000000));
- __ Assert(eq, kUnableToEncodeValueAsSmi);
+ __ Assert(eq, "Unable to encode value as smi");
}
__ SmiTag(reg);
}
@@ -313,12 +313,12 @@ void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
- masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnArm);
+ masm->Abort("LiveEdit frame dropping is not supported on arm");
}
void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
- masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnArm);
+ masm->Abort("LiveEdit frame dropping is not supported on arm");
}
const bool Debug::kFrameDropperSupported = false;
diff --git a/chromium/v8/src/arm/full-codegen-arm.cc b/chromium/v8/src/arm/full-codegen-arm.cc
index b73006a17d9..ea7b73f2fe9 100644
--- a/chromium/v8/src/arm/full-codegen-arm.cc
+++ b/chromium/v8/src/arm/full-codegen-arm.cc
@@ -786,9 +786,9 @@ void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
// Check that we're not inside a with or catch context.
__ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
__ CompareRoot(r1, Heap::kWithContextMapRootIndex);
- __ Check(ne, kDeclarationInWithContext);
+ __ Check(ne, "Declaration in with context.");
__ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
- __ Check(ne, kDeclarationInCatchContext);
+ __ Check(ne, "Declaration in catch context.");
}
}
@@ -2512,7 +2512,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Check for an uninitialized let binding.
__ ldr(r2, location);
__ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
- __ Check(eq, kLetBindingReInitialization);
+ __ Check(eq, "Let binding re-initialization.");
}
// Perform the assignment.
__ str(r0, location);
@@ -3473,23 +3473,23 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
Register value,
uint32_t encoding_mask) {
__ SmiTst(index);
- __ Check(eq, kNonSmiIndex);
+ __ Check(eq, "Non-smi index");
__ SmiTst(value);
- __ Check(eq, kNonSmiValue);
+ __ Check(eq, "Non-smi value");
__ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
__ cmp(index, ip);
- __ Check(lt, kIndexIsTooLarge);
+ __ Check(lt, "Index is too large");
__ cmp(index, Operand(Smi::FromInt(0)));
- __ Check(ge, kIndexIsNegative);
+ __ Check(ge, "Index is negative");
__ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
__ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
__ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
__ cmp(ip, Operand(encoding_mask));
- __ Check(eq, kUnexpectedStringType);
+ __ Check(eq, "Unexpected string type");
}
@@ -3849,7 +3849,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
Handle<FixedArray> jsfunction_result_caches(
isolate()->native_context()->jsfunction_result_caches());
if (jsfunction_result_caches->length() <= cache_id) {
- __ Abort(kAttemptToUseUndefinedCache);
+ __ Abort("Attempt to use undefined cache.");
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
context()->Plug(r0);
return;
@@ -4030,7 +4030,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// elements_end: Array end.
if (generate_debug_code_) {
__ cmp(array_length, Operand::Zero());
- __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
+ __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin");
}
__ bind(&loop);
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
@@ -4349,12 +4349,35 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
+ case Token::SUB:
+ EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
+ break;
+
+ case Token::BIT_NOT:
+ EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
+ break;
+
default:
UNREACHABLE();
}
}
+void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
+ const char* comment) {
+ // TODO(svenpanne): Allowing format strings in Comment would be nice here...
+ Comment cmt(masm_, comment);
+ UnaryOpStub stub(expr->op());
+ // UnaryOpStub expects the argument to be in the
+ // accumulator register r0.
+ VisitForAccumulatorValue(expr->expression());
+ SetSourcePosition(expr->position());
+ CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
+ expr->UnaryOperationFeedbackId());
+ context()->Plug(r0);
+}
+
+
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
diff --git a/chromium/v8/src/arm/lithium-arm.cc b/chromium/v8/src/arm/lithium-arm.cc
index 998b73b62e9..e9ae04a1ee8 100644
--- a/chromium/v8/src/arm/lithium-arm.cc
+++ b/chromium/v8/src/arm/lithium-arm.cc
@@ -437,7 +437,7 @@ LPlatformChunk* LChunkBuilder::Build() {
}
-void LChunkBuilder::Abort(BailoutReason reason) {
+void LChunkBuilder::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -593,10 +593,8 @@ LInstruction* LChunkBuilder::DefineFixedDouble(
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
HEnvironment* hydrogen_env = current_block_->last_environment();
int argument_index_accumulator = 0;
- ZoneList<HValue*> objects_to_materialize(0, zone());
instr->set_environment(CreateEnvironment(hydrogen_env,
- &argument_index_accumulator,
- &objects_to_materialize));
+ &argument_index_accumulator));
return instr;
}
@@ -647,7 +645,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
- Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
+ Abort("Out of virtual registers while trying to allocate temp register.");
vreg = 0;
}
operand->set_virtual_register(vreg);
@@ -885,7 +883,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
}
#endif
- instr->set_position(position_);
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -901,13 +898,11 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LEnvironment* LChunkBuilder::CreateEnvironment(
HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize) {
+ int* argument_index_accumulator) {
if (hydrogen_env == NULL) return NULL;
- LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
- argument_index_accumulator,
- objects_to_materialize);
+ LEnvironment* outer =
+ CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
@@ -922,16 +917,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- int object_index = objects_to_materialize->length();
for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
- LOperand* op;
HValue* value = hydrogen_env->values()->at(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
+ LOperand* op = NULL;
+ if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
+ op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
} else {
@@ -942,33 +937,15 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
value->CheckFlag(HInstruction::kUint32));
}
- for (int i = object_index; i < objects_to_materialize->length(); ++i) {
- HValue* object_to_materialize = objects_to_materialize->at(i);
- int previously_materialized_object = -1;
- for (int prev = 0; prev < i; ++prev) {
- if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
- previously_materialized_object = prev;
- break;
- }
- }
- int length = object_to_materialize->OperandCount();
- bool is_arguments = object_to_materialize->IsArgumentsObject();
- if (previously_materialized_object >= 0) {
- result->AddDuplicateObject(previously_materialized_object);
- continue;
- } else {
- result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
- }
- for (int i = is_arguments ? 1 : 0; i < length; ++i) {
- LOperand* op;
- HValue* value = object_to_materialize->OperandAt(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
- } else {
- ASSERT(!value->IsPushArgument());
- op = UseAny(value);
- }
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ LOperand* op = UseAny(value);
result->AddValue(op,
value->representation(),
value->CheckFlag(HInstruction::kUint32));
@@ -1348,6 +1325,15 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
}
+LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
+ ASSERT(instr->value()->representation().IsInteger32());
+ ASSERT(instr->representation().IsInteger32());
+ if (instr->HasNoUses()) return NULL;
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new(zone()) LBitNotI(value));
+}
+
+
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
@@ -1709,8 +1695,9 @@ LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(r));
- ASSERT(instr->right()->representation().Equals(r));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->left()->representation().Equals(
+ instr->right()->representation()));
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
return new(zone()) LCompareNumericAndBranch(left, right);
@@ -1733,13 +1720,6 @@ LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
}
-LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
- HCompareHoleAndBranch* instr) {
- LOperand* object = UseRegisterAtStart(instr->object());
- return new(zone()) LCmpHoleAndBranch(object);
-}
-
-
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
@@ -1852,6 +1832,17 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
+LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
+ return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
@@ -2025,6 +2016,19 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
}
+LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
+ LUnallocated* temp1 = NULL;
+ LOperand* temp2 = NULL;
+ if (!instr->CanOmitPrototypeChecks()) {
+ temp1 = TempRegister();
+ temp2 = TempRegister();
+ }
+ LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
+ if (instr->CanOmitPrototypeChecks()) return result;
+ return AssignEnvironment(result);
+}
+
+
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckFunction(value));
@@ -2033,16 +2037,10 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
LOperand* value = NULL;
- if (!instr->CanOmitMapChecks()) {
- value = UseRegisterAtStart(instr->value());
- if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
- }
- LCheckMaps* result = new(zone()) LCheckMaps(value);
- if (!instr->CanOmitMapChecks()) {
- AssignEnvironment(result);
- if (instr->has_migration_target()) return AssignPointerMap(result);
- }
- return result;
+ if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
+ LInstruction* result = new(zone()) LCheckMaps(value);
+ if (instr->CanOmitMapChecks()) return result;
+ return AssignEnvironment(result);
}
@@ -2153,6 +2151,23 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
}
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+ HLoadNamedFieldPolymorphic* instr) {
+ ASSERT(instr->representation().IsTagged());
+ if (instr->need_generic()) {
+ LOperand* obj = UseFixed(instr->object(), r0);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
+ return MarkAsCall(DefineFixed(result, r0), instr);
+ } else {
+ LOperand* obj = UseRegisterAtStart(instr->object());
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
+ return AssignEnvironment(DefineAsRegister(result));
+ }
+}
+
+
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), r0);
LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0);
@@ -2307,7 +2322,7 @@ LInstruction* LChunkBuilder::DoTrapAllocationMemento(
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool is_in_object = instr->access().IsInobject();
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
+ bool needs_write_barrier_for_map = !instr->transition().is_null() &&
instr->NeedsWriteBarrierForMap();
LOperand* obj;
@@ -2427,7 +2442,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
- Abort(kTooManySpillSlotsNeededForOSR);
+ Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
@@ -2449,12 +2464,6 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
}
-LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
- // There are no real uses of a captured object.
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
info()->MarkAsRequiresFrame();
LOperand* args = UseRegister(instr->arguments());
diff --git a/chromium/v8/src/arm/lithium-arm.h b/chromium/v8/src/arm/lithium-arm.h
index d81dc0f57cd..c568ad6f95e 100644
--- a/chromium/v8/src/arm/lithium-arm.h
+++ b/chromium/v8/src/arm/lithium-arm.h
@@ -50,6 +50,7 @@ class LCodeGen;
V(ArithmeticD) \
V(ArithmeticT) \
V(BitI) \
+ V(BitNotI) \
V(BoundsCheck) \
V(Branch) \
V(CallConstantFunction) \
@@ -67,6 +68,7 @@ class LCodeGen;
V(CheckNonSmi) \
V(CheckMaps) \
V(CheckMapValue) \
+ V(CheckPrototypeMaps) \
V(CheckSmi) \
V(ClampDToUint8) \
V(ClampIToUint8) \
@@ -74,7 +76,6 @@ class LCodeGen;
V(ClassOfTestAndBranch) \
V(CompareNumericAndBranch) \
V(CmpObjectEqAndBranch) \
- V(CmpHoleAndBranch) \
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
@@ -127,6 +128,7 @@ class LCodeGen;
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
+ V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -208,12 +210,9 @@ class LCodeGen;
class LInstruction: public ZoneObject {
public:
LInstruction()
- : environment_(NULL),
- hydrogen_value_(NULL),
- bit_field_(IsCallBits::encode(false)) {
- set_position(RelocInfo::kNoPosition);
- }
-
+ : environment_(NULL),
+ hydrogen_value_(NULL),
+ is_call_(false) { }
virtual ~LInstruction() { }
virtual void CompileToNative(LCodeGen* generator) = 0;
@@ -252,30 +251,20 @@ class LInstruction: public ZoneObject {
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
- // The 31 bits PositionBits is used to store the int position value. And the
- // position value may be RelocInfo::kNoPosition (-1). The accessor always
- // +1/-1 so that the encoded value of position in bit_field_ is always >= 0
- // and can fit into the 31 bits PositionBits.
- void set_position(int pos) {
- bit_field_ = PositionBits::update(bit_field_, pos + 1);
- }
- int position() { return PositionBits::decode(bit_field_) - 1; }
-
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
- void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
- bool IsCall() const { return IsCallBits::decode(bit_field_); }
+ void MarkAsCall() { is_call_ = true; }
// Interface to the register allocator and iterators.
- bool ClobbersTemps() const { return IsCall(); }
- bool ClobbersRegisters() const { return IsCall(); }
- bool ClobbersDoubleRegisters() const { return IsCall(); }
+ bool ClobbersTemps() const { return is_call_; }
+ bool ClobbersRegisters() const { return is_call_; }
+ bool ClobbersDoubleRegisters() const { return is_call_; }
// Interface to the register allocator and iterators.
- bool IsMarkedAsCall() const { return IsCall(); }
+ bool IsMarkedAsCall() const { return is_call_; }
virtual bool HasResult() const = 0;
virtual LOperand* result() const = 0;
@@ -299,13 +288,10 @@ class LInstruction: public ZoneObject {
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
- class IsCallBits: public BitField<bool, 0, 1> {};
- class PositionBits: public BitField<int, 1, 31> {};
-
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
- int bit_field_;
+ bool is_call_;
};
@@ -895,24 +881,12 @@ class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
LOperand* left() { return inputs_[0]; }
LOperand* right() { return inputs_[1]; }
- DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
+ DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch,
+ "cmp-object-eq-and-branch")
DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
};
-class LCmpHoleAndBranch: public LControlInstruction<1, 0> {
- public:
- explicit LCmpHoleAndBranch(LOperand* object) {
- inputs_[0] = object;
- }
-
- LOperand* object() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
-};
-
-
class LIsObjectAndBranch: public LControlInstruction<1, 1> {
public:
LIsObjectAndBranch(LOperand* value, LOperand* temp) {
@@ -1404,6 +1378,18 @@ class LThrow: public LTemplateInstruction<0, 1, 0> {
};
+class LBitNotI: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LBitNotI(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ LOperand* value() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
+};
+
+
class LAddI: public LTemplateInstruction<1, 2, 0> {
public:
LAddI(LOperand* left, LOperand* right) {
@@ -1539,6 +1525,19 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
};
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ LOperand* object() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+ DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+};
+
+
class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadNamedGeneric(LOperand* object) {
@@ -2151,7 +2150,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
virtual void PrintDataTo(StringStream* stream);
- Handle<Map> transition() const { return hydrogen()->transition_map(); }
+ Handle<Map> transition() const { return hydrogen()->transition(); }
Representation representation() const {
return hydrogen()->field_representation();
}
@@ -2353,6 +2352,26 @@ class LCheckMaps: public LTemplateInstruction<0, 1, 0> {
};
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 2> {
+ public:
+ LCheckPrototypeMaps(LOperand* temp, LOperand* temp2) {
+ temps_[0] = temp;
+ temps_[1] = temp2;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+ LOperand* temp2() { return temps_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
+ DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
+
+ ZoneList<Handle<JSObject> >* prototypes() const {
+ return hydrogen()->prototypes();
+ }
+ ZoneList<Handle<Map> >* maps() const { return hydrogen()->maps(); }
+};
+
+
class LCheckSmi: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCheckSmi(LOperand* value) {
@@ -2651,7 +2670,7 @@ class LChunkBuilder BASE_EMBEDDED {
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
// Methods for getting operands for Use / Define / Temp.
LUnallocated* ToUnallocated(Register reg);
@@ -2733,8 +2752,7 @@ class LChunkBuilder BASE_EMBEDDED {
CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize);
+ int* argument_index_accumulator);
void VisitInstruction(HInstruction* current);
diff --git a/chromium/v8/src/arm/lithium-codegen-arm.cc b/chromium/v8/src/arm/lithium-codegen-arm.cc
index 9ec80f819a0..cf1e7c70f5f 100644
--- a/chromium/v8/src/arm/lithium-codegen-arm.cc
+++ b/chromium/v8/src/arm/lithium-codegen-arm.cc
@@ -91,7 +91,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
}
-void LCodeGen::Abort(BailoutReason reason) {
+void LCodeGen::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -274,8 +274,6 @@ bool LCodeGen::GenerateBody() {
instr->Mnemonic());
}
- RecordAndUpdatePosition(instr->position());
-
instr->CompileToNative(this);
}
EnsureSpaceForLazyDeopt();
@@ -289,10 +287,6 @@ bool LCodeGen::GenerateDeferredCode() {
if (deferred_.length() > 0) {
for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
LDeferredCode* code = deferred_[i];
-
- int pos = instructions_->at(code->instruction_index())->position();
- RecordAndUpdatePosition(pos);
-
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",
code->instruction_index(),
@@ -340,7 +334,7 @@ bool LCodeGen::GenerateDeoptJumpTable() {
// 32bit data after it.
if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) +
deopt_jump_table_.length() * 7)) {
- Abort(kGeneratedCodeIsTooLarge);
+ Abort("Generated code is too large");
}
if (deopt_jump_table_.length() > 0) {
@@ -429,7 +423,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
ASSERT(literal->IsNumber());
__ mov(scratch, Operand(static_cast<int32_t>(literal->Number())));
} else if (r.IsDouble()) {
- Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
+ Abort("EmitLoadRegister: Unsupported double immediate.");
} else {
ASSERT(r.IsTagged());
__ LoadObject(scratch, literal);
@@ -467,9 +461,9 @@ DwVfpRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
__ vcvt_f64_s32(dbl_scratch, flt_scratch);
return dbl_scratch;
} else if (r.IsDouble()) {
- Abort(kUnsupportedDoubleImmediate);
+ Abort("unsupported double immediate");
} else if (r.IsTagged()) {
- Abort(kUnsupportedTaggedImmediate);
+ Abort("unsupported tagged immediate");
}
} else if (op->IsStackSlot() || op->IsArgument()) {
// TODO(regis): Why is vldr not taking a MemOperand?
@@ -540,14 +534,14 @@ Operand LCodeGen::ToOperand(LOperand* op) {
ASSERT(constant->HasInteger32Value());
return Operand(constant->Integer32Value());
} else if (r.IsDouble()) {
- Abort(kToOperandUnsupportedDoubleImmediate);
+ Abort("ToOperand Unsupported double immediate.");
}
ASSERT(r.IsTagged());
return Operand(constant->handle());
} else if (op->IsRegister()) {
return Operand(ToRegister(op));
} else if (op->IsDoubleRegister()) {
- Abort(kToOperandIsDoubleRegisterUnimplemented);
+ Abort("ToOperand IsDoubleRegister unimplemented");
return Operand::Zero();
}
// Stack slots not implemented, use ToMemOperand instead.
@@ -611,57 +605,37 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
break;
}
- int object_index = 0;
- int dematerialized_index = 0;
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
- AddToTranslation(environment,
- translation,
+
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
+ AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- &object_index,
- &dematerialized_index);
+ environment->HasUint32ValueAt(i));
}
}
-void LCodeGen::AddToTranslation(LEnvironment* environment,
- Translation* translation,
+void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer) {
- if (op == LEnvironment::materialization_marker()) {
- int object_index = (*object_index_pointer)++;
- if (environment->ObjectIsDuplicateAt(object_index)) {
- int dupe_of = environment->ObjectDuplicateOfAt(object_index);
- translation->DuplicateObject(dupe_of);
- return;
- }
- int object_length = environment->ObjectLengthAt(object_index);
- if (environment->ObjectIsArgumentsAt(object_index)) {
- translation->BeginArgumentsObject(object_length);
- } else {
- translation->BeginCapturedObject(object_length);
- }
- int dematerialized_index = *dematerialized_index_pointer;
- int env_offset = environment->translation_size() + dematerialized_index;
- *dematerialized_index_pointer += object_length;
- for (int i = 0; i < object_length; ++i) {
- LOperand* value = environment->values()->at(env_offset + i);
- AddToTranslation(environment,
- translation,
- value,
- environment->HasTaggedValueAt(env_offset + i),
- environment->HasUint32ValueAt(env_offset + i),
- object_index_pointer,
- dematerialized_index_pointer);
- }
- return;
- }
-
+ bool is_uint32) {
if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
@@ -788,7 +762,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
}
-void LCodeGen::DeoptimizeIf(Condition condition,
+void LCodeGen::DeoptimizeIf(Condition cc,
LEnvironment* environment,
Deoptimizer::BailoutType bailout_type) {
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
@@ -798,7 +772,7 @@ void LCodeGen::DeoptimizeIf(Condition condition,
Address entry =
Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
if (entry == NULL) {
- Abort(kBailoutWasNotPrepared);
+ Abort("bailout was not prepared");
return;
}
@@ -811,12 +785,12 @@ void LCodeGen::DeoptimizeIf(Condition condition,
return;
}
- if (info()->ShouldTrapOnDeopt()) {
- __ stop("trap_on_deopt", condition);
+ if (FLAG_trap_on_deopt && info()->IsOptimizing()) {
+ __ stop("trap_on_deopt", cc);
}
ASSERT(info()->IsStub() || frame_is_built_);
- if (condition == al && frame_is_built_) {
+ if (cc == al && frame_is_built_) {
__ Call(entry, RelocInfo::RUNTIME_ENTRY);
} else {
// We often have several deopts to the same entry, reuse the last
@@ -830,17 +804,17 @@ void LCodeGen::DeoptimizeIf(Condition condition,
!frame_is_built_);
deopt_jump_table_.Add(table_entry, zone());
}
- __ b(condition, &deopt_jump_table_.last().label);
+ __ b(cc, &deopt_jump_table_.last().label);
}
}
-void LCodeGen::DeoptimizeIf(Condition condition,
+void LCodeGen::DeoptimizeIf(Condition cc,
LEnvironment* environment) {
Deoptimizer::BailoutType bailout_type = info()->IsStub()
? Deoptimizer::LAZY
: Deoptimizer::EAGER;
- DeoptimizeIf(condition, environment, bailout_type);
+ DeoptimizeIf(cc, environment, bailout_type);
}
@@ -1003,14 +977,6 @@ void LCodeGen::RecordPosition(int position) {
}
-void LCodeGen::RecordAndUpdatePosition(int position) {
- if (position >= 0 && position != old_position_) {
- masm()->positions_recorder()->RecordPosition(position);
- old_position_ = position;
- }
-}
-
-
static const char* LabelType(LLabel* label) {
if (label->is_loop_header()) return " (loop header)";
if (label->is_osr_entry()) return " (OSR entry)";
@@ -1703,11 +1669,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
__ orr(result, left, right);
break;
case Token::BIT_XOR:
- if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
- __ mvn(result, Operand(left));
- } else {
- __ eor(result, left, right);
- }
+ __ eor(result, left, right);
break;
default:
UNREACHABLE();
@@ -1974,7 +1936,7 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
__ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING
? one_byte_seq_type : two_byte_seq_type));
- __ Check(eq, kUnexpectedStringType);
+ __ Check(eq, "Unexpected string type");
}
__ add(ip,
@@ -1991,6 +1953,13 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
}
+void LCodeGen::DoBitNotI(LBitNotI* instr) {
+ Register input = ToRegister(instr->value());
+ Register result = ToRegister(instr->result());
+ __ mvn(result, Operand(input));
+}
+
+
void LCodeGen::DoThrow(LThrow* instr) {
Register input_reg = EmitLoadRegister(instr->value(), ip);
__ push(input_reg);
@@ -2152,32 +2121,25 @@ int LCodeGen::GetNextEmittedBlock() const {
}
template<class InstrType>
-void LCodeGen::EmitBranch(InstrType instr, Condition condition) {
+void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
int left_block = instr->TrueDestination(chunk_);
int right_block = instr->FalseDestination(chunk_);
int next_block = GetNextEmittedBlock();
- if (right_block == left_block || condition == al) {
+ if (right_block == left_block || cc == al) {
EmitGoto(left_block);
} else if (left_block == next_block) {
- __ b(NegateCondition(condition), chunk_->GetAssemblyLabel(right_block));
+ __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
} else if (right_block == next_block) {
- __ b(condition, chunk_->GetAssemblyLabel(left_block));
+ __ b(cc, chunk_->GetAssemblyLabel(left_block));
} else {
- __ b(condition, chunk_->GetAssemblyLabel(left_block));
+ __ b(cc, chunk_->GetAssemblyLabel(left_block));
__ b(chunk_->GetAssemblyLabel(right_block));
}
}
-template<class InstrType>
-void LCodeGen::EmitFalseBranch(InstrType instr, Condition condition) {
- int false_block = instr->FalseDestination(chunk_);
- __ b(condition, chunk_->GetAssemblyLabel(false_block));
-}
-
-
void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
__ stop("LBreak");
}
@@ -2433,26 +2395,6 @@ void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
}
-void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
- if (instr->hydrogen()->representation().IsTagged()) {
- Register input_reg = ToRegister(instr->object());
- __ mov(ip, Operand(factory()->the_hole_value()));
- __ cmp(input_reg, ip);
- EmitBranch(instr, eq);
- return;
- }
-
- DwVfpRegister input_reg = ToDoubleRegister(instr->object());
- __ VFPCompareAndSetFlags(input_reg, input_reg);
- EmitFalseBranch(instr, vc);
-
- Register scratch = scratch0();
- __ VmovHigh(scratch, input_reg);
- __ cmp(scratch, Operand(kHoleNanUpper32));
- EmitBranch(instr, eq);
-}
-
-
Condition LCodeGen::EmitIsObject(Register input,
Register temp1,
Label* is_not_object,
@@ -3079,6 +3021,91 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
}
+void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env) {
+ LookupResult lookup(isolate());
+ type->LookupDescriptor(NULL, *name, &lookup);
+ ASSERT(lookup.IsFound() || lookup.IsCacheable());
+ if (lookup.IsField()) {
+ int index = lookup.GetLocalFieldIndexFromMap(*type);
+ int offset = index * kPointerSize;
+ if (index < 0) {
+ // Negative property indices are in-object properties, indexed
+ // from the end of the fixed part of the object.
+ __ ldr(result, FieldMemOperand(object, offset + type->instance_size()));
+ } else {
+ // Non-negative property indices are in the properties array.
+ __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
+ }
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
+ } else {
+ // Negative lookup.
+ // Check prototypes.
+ Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
+ Heap* heap = type->GetHeap();
+ while (*current != heap->null_value()) {
+ __ LoadHeapObject(result, current);
+ __ ldr(result, FieldMemOperand(result, HeapObject::kMapOffset));
+ __ cmp(result, Operand(Handle<Map>(current->map())));
+ DeoptimizeIf(ne, env);
+ current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
+ }
+ __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
+ }
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+ Register object = ToRegister(instr->object());
+ Register result = ToRegister(instr->result());
+ Register object_map = scratch0();
+
+ int map_count = instr->hydrogen()->types()->length();
+ bool need_generic = instr->hydrogen()->need_generic();
+
+ if (map_count == 0 && !need_generic) {
+ DeoptimizeIf(al, instr->environment());
+ return;
+ }
+ Handle<String> name = instr->hydrogen()->name();
+ Label done;
+ __ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
+ for (int i = 0; i < map_count; ++i) {
+ bool last = (i == map_count - 1);
+ Handle<Map> map = instr->hydrogen()->types()->at(i);
+ Label check_passed;
+ __ CompareMap(object_map, map, &check_passed);
+ if (last && !need_generic) {
+ DeoptimizeIf(ne, instr->environment());
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstantFunction(
+ result, object, map, name, instr->environment());
+ } else {
+ Label next;
+ __ b(ne, &next);
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstantFunction(
+ result, object, map, name, instr->environment());
+ __ b(&done);
+ __ bind(&next);
+ }
+ }
+ if (need_generic) {
+ __ mov(r2, Operand(name));
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
+ }
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(r0));
ASSERT(ToRegister(instr->result()).is(r0));
@@ -3173,7 +3200,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -3257,7 +3284,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -3518,7 +3545,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
void LCodeGen::DoPushArgument(LPushArgument* instr) {
LOperand* argument = instr->value();
if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
- Abort(kDoPushArgumentNotImplementedForDoubleType);
+ Abort("DoPushArgument not implemented for double type.");
} else {
Register argument_reg = EmitLoadRegister(argument, ip);
__ push(argument_reg);
@@ -3738,7 +3765,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
DwVfpRegister input = ToDoubleRegister(instr->value());
DwVfpRegister result = ToDoubleRegister(instr->result());
__ vabs(result, input);
- } else if (r.IsSmiOrInteger32()) {
+ } else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else {
// Representation is tagged.
@@ -4251,14 +4278,14 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
}
-void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) {
+void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
if (FLAG_debug_code && check->hydrogen()->skip_check()) {
Label done;
- __ b(NegateCondition(condition), &done);
+ __ b(NegateCondition(cc), &done);
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
- DeoptimizeIf(condition, check->environment());
+ DeoptimizeIf(cc, check->environment());
}
}
@@ -4292,7 +4319,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -4365,7 +4392,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -4388,7 +4415,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
if (masm()->emit_debug_code()) {
__ vmrs(ip);
__ tst(ip, Operand(kVFPDefaultNaNModeControlBit));
- __ Assert(ne, kDefaultNaNModeNotSet);
+ __ Assert(ne, "Default NaN mode not set");
}
__ VFPCanonicalizeNaN(value);
}
@@ -4489,13 +4516,12 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
scratch, GetLinkRegisterState(), kDontSaveFPRegs);
} else {
- PushSafepointRegistersScope scope(
- this, Safepoint::kWithRegistersAndDoubles);
+ PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
__ Move(r0, object_reg);
__ Move(r1, to_map);
TransitionElementsKindStub stub(from_kind, to_kind);
__ CallStub(&stub);
- RecordSafepointWithRegistersAndDoubles(
+ RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
}
__ bind(&not_applicable);
@@ -4783,6 +4809,29 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
Register temp1 = ToRegister(instr->temp());
Register temp2 = ToRegister(instr->temp2());
+ bool convert_hole = false;
+ HValue* change_input = instr->hydrogen()->value();
+ if (change_input->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(change_input);
+ convert_hole = load->UsesMustHandleHole();
+ }
+
+ Label no_special_nan_handling;
+ Label done;
+ if (convert_hole) {
+ DwVfpRegister input_reg = ToDoubleRegister(instr->value());
+ __ VFPCompareAndSetFlags(input_reg, input_reg);
+ __ b(vc, &no_special_nan_handling);
+ __ VmovHigh(scratch, input_reg);
+ __ cmp(scratch, Operand(kHoleNanUpper32));
+ // If not the hole NaN, force the NaN to be canonical.
+ __ VFPCanonicalizeNaN(input_reg, ne);
+ __ b(ne, &no_special_nan_handling);
+ __ Move(reg, factory()->the_hole_value());
+ __ b(&done);
+ }
+
+ __ bind(&no_special_nan_handling);
DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
if (FLAG_inline_new) {
__ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
@@ -4796,6 +4845,7 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
__ vstr(input_reg, reg, HeapNumber::kValueOffset);
// Now that we have finished with the object's real address tag it
__ add(reg, reg, Operand(kHeapObjectTag));
+ __ bind(&done);
}
@@ -4835,7 +4885,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
DwVfpRegister result_reg,
- bool can_convert_undefined_to_nan,
+ bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
@@ -4845,7 +4895,9 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
Label load_smi, heap_number, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
@@ -4853,7 +4905,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
__ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(scratch, Operand(ip));
- if (!can_convert_undefined_to_nan) {
+ if (!allow_undefined_as_nan) {
DeoptimizeIf(ne, env);
} else {
Label heap_number, convert;
@@ -4862,6 +4914,11 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Convert undefined (and hole) to NaN.
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(input_reg, Operand(ip));
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ b(eq, &convert);
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ cmp(input_reg, Operand(ip));
+ }
DeoptimizeIf(ne, env);
__ bind(&convert);
@@ -5002,12 +5059,21 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
Register input_reg = ToRegister(input);
DwVfpRegister result_reg = ToDoubleRegister(result);
+ NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
- NumberUntagDMode mode = value->representation().IsSmi()
- ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
+ if (value->type().IsSmi()) {
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
+ }
+ }
+ }
EmitNumberUntagD(input_reg, result_reg,
- instr->hydrogen()->can_convert_undefined_to_nan(),
+ instr->hydrogen()->allow_undefined_as_nan(),
instr->hydrogen()->deoptimize_on_minus_zero(),
instr->environment(),
mode);
@@ -5137,7 +5203,7 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
AllowDeferredHandleDereference smi_check;
if (isolate()->heap()->InNewSpace(*target)) {
Register reg = ToRegister(instr->value());
- Handle<Cell> cell = isolate()->factory()->NewCell(target);
+ Handle<Cell> cell = isolate()->factory()->NewPropertyCell(target);
__ mov(ip, Operand(Handle<Object>(cell)));
__ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset));
__ cmp(reg, ip);
@@ -5148,67 +5214,33 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
}
-void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
- {
- PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
- __ push(object);
- CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr);
- __ StoreToSafepointRegisterSlot(r0, scratch0());
- }
- __ tst(scratch0(), Operand(kSmiTagMask));
- DeoptimizeIf(eq, instr->environment());
+void LCodeGen::DoCheckMapCommon(Register map_reg,
+ Handle<Map> map,
+ LEnvironment* env) {
+ Label success;
+ __ CompareMap(map_reg, map, &success);
+ DeoptimizeIf(ne, env);
+ __ bind(&success);
}
void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
- class DeferredCheckMaps: public LDeferredCode {
- public:
- DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
- : LDeferredCode(codegen), instr_(instr), object_(object) {
- SetExit(check_maps());
- }
- virtual void Generate() {
- codegen()->DoDeferredInstanceMigration(instr_, object_);
- }
- Label* check_maps() { return &check_maps_; }
- virtual LInstruction* instr() { return instr_; }
- private:
- LCheckMaps* instr_;
- Label check_maps_;
- Register object_;
- };
-
if (instr->hydrogen()->CanOmitMapChecks()) return;
Register map_reg = scratch0();
-
LOperand* input = instr->value();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
+ Label success;
SmallMapList* map_set = instr->hydrogen()->map_set();
__ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-
- DeferredCheckMaps* deferred = NULL;
- if (instr->hydrogen()->has_migration_target()) {
- deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
- __ bind(deferred->check_maps());
- }
-
- Label success;
for (int i = 0; i < map_set->length() - 1; i++) {
Handle<Map> map = map_set->at(i);
__ CompareMap(map_reg, map, &success);
__ b(eq, &success);
}
-
Handle<Map> map = map_set->last();
- __ CompareMap(map_reg, map, &success);
- if (instr->hydrogen()->has_migration_target()) {
- __ b(ne, deferred->entry());
- } else {
- DeoptimizeIf(ne, instr->environment());
- }
-
+ DoCheckMapCommon(map_reg, map, instr->environment());
__ bind(&success);
}
@@ -5263,6 +5295,25 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
}
+void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
+ if (instr->hydrogen()->CanOmitPrototypeChecks()) return;
+
+ Register prototype_reg = ToRegister(instr->temp());
+ Register map_reg = ToRegister(instr->temp2());
+
+ ZoneList<Handle<JSObject> >* prototypes = instr->prototypes();
+ ZoneList<Handle<Map> >* maps = instr->maps();
+
+ ASSERT(prototypes->length() == maps->length());
+
+ for (int i = 0; i < prototypes->length(); i++) {
+ __ LoadHeapObject(prototype_reg, prototypes->at(i));
+ __ ldr(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
+ DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
+ }
+}
+
+
void LCodeGen::DoAllocate(LAllocate* instr) {
class DeferredAllocate: public LDeferredCode {
public:
@@ -5597,8 +5648,6 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
if (info()->IsStub() && type == Deoptimizer::EAGER) {
type = Deoptimizer::LAZY;
}
-
- Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
DeoptimizeIf(al, instr->environment(), type);
}
diff --git a/chromium/v8/src/arm/lithium-codegen-arm.h b/chromium/v8/src/arm/lithium-codegen-arm.h
index d0bfcbbb94e..21f792153ba 100644
--- a/chromium/v8/src/arm/lithium-codegen-arm.h
+++ b/chromium/v8/src/arm/lithium-codegen-arm.h
@@ -66,8 +66,7 @@ class LCodeGen BASE_EMBEDDED {
frame_is_built_(false),
safepoints_(info->zone()),
resolver_(this),
- expected_safepoint_kind_(Safepoint::kSimple),
- old_position_(RelocInfo::kNoPosition) {
+ expected_safepoint_kind_(Safepoint::kSimple) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
}
@@ -116,7 +115,7 @@ class LCodeGen BASE_EMBEDDED {
DwVfpRegister EmitLoadDoubleRegister(LOperand* op,
SwVfpRegister flt_scratch,
DwVfpRegister dbl_scratch);
- int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
+ int ToRepresentation(LConstantOperand* op, const Representation& r) const;
int32_t ToInteger32(LConstantOperand* op) const;
Smi* ToSmi(LConstantOperand* op) const;
double ToDouble(LConstantOperand* op) const;
@@ -155,7 +154,8 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
- void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
+
+ void DoCheckMapCommon(Register map_reg, Handle<Map> map, LEnvironment* env);
// Parallel move support.
void DoParallelMove(LParallelMove* move);
@@ -214,7 +214,7 @@ class LCodeGen BASE_EMBEDDED {
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
void FPRINTF_CHECKING Comment(const char* format, ...);
void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
@@ -281,19 +281,16 @@ class LCodeGen BASE_EMBEDDED {
void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode);
- void DeoptimizeIf(Condition condition,
+ void DeoptimizeIf(Condition cc,
LEnvironment* environment,
Deoptimizer::BailoutType bailout_type);
- void DeoptimizeIf(Condition condition, LEnvironment* environment);
- void ApplyCheckIf(Condition condition, LBoundsCheck* check);
+ void DeoptimizeIf(Condition cc, LEnvironment* environment);
+ void ApplyCheckIf(Condition cc, LBoundsCheck* check);
- void AddToTranslation(LEnvironment* environment,
- Translation* translation,
+ void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -319,14 +316,11 @@ class LCodeGen BASE_EMBEDDED {
int arguments,
Safepoint::DeoptMode mode);
void RecordPosition(int position);
- void RecordAndUpdatePosition(int position);
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
template<class InstrType>
- void EmitBranch(InstrType instr, Condition condition);
- template<class InstrType>
- void EmitFalseBranch(InstrType instr, Condition condition);
+ void EmitBranch(InstrType instr, Condition cc);
void EmitNumberUntagD(Register input,
DwVfpRegister result,
bool allow_undefined_as_nan,
@@ -362,6 +356,12 @@ class LCodeGen BASE_EMBEDDED {
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp1, Register temp2);
+ void EmitLoadFieldOrConstantFunction(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env);
+
// Emits optimized code to deep-copy the contents of statically known
// object graphs (e.g. object literal boilerplate).
void EmitDeepCopy(Handle<JSObject> object,
@@ -418,8 +418,6 @@ class LCodeGen BASE_EMBEDDED {
Safepoint::Kind expected_safepoint_kind_;
- int old_position_;
-
class PushSafepointRegistersScope BASE_EMBEDDED {
public:
PushSafepointRegistersScope(LCodeGen* codegen,
diff --git a/chromium/v8/src/arm/lithium-gap-resolver-arm.cc b/chromium/v8/src/arm/lithium-gap-resolver-arm.cc
index 88ac7a2a21d..7a3c96892c2 100644
--- a/chromium/v8/src/arm/lithium-gap-resolver-arm.cc
+++ b/chromium/v8/src/arm/lithium-gap-resolver-arm.cc
@@ -254,7 +254,7 @@ void LGapResolver::EmitMove(int index) {
} else {
__ LoadObject(dst, cgen_->ToHandle(constant_source));
}
- } else if (destination->IsDoubleRegister()) {
+ } else if (source->IsDoubleRegister()) {
DwVfpRegister result = cgen_->ToDoubleRegister(destination);
double v = cgen_->ToDouble(constant_source);
__ Vmov(result, v, ip);
diff --git a/chromium/v8/src/arm/macro-assembler-arm.cc b/chromium/v8/src/arm/macro-assembler-arm.cc
index a56744bf597..cd124610f97 100644
--- a/chromium/v8/src/arm/macro-assembler-arm.cc
+++ b/chromium/v8/src/arm/macro-assembler-arm.cc
@@ -375,13 +375,16 @@ void MacroAssembler::LoadRoot(Register destination,
Heap::RootListIndex index,
Condition cond) {
if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
- isolate()->heap()->RootCanBeTreatedAsConstant(index) &&
+ !Heap::RootCanBeWrittenAfterInitialization(index) &&
!predictable_code_size()) {
- // The CPU supports fast immediate values, and this root will never
- // change. We will load it as a relocatable immediate value.
- Handle<Object> root(&isolate()->heap()->roots_array_start()[index]);
- mov(destination, Operand(root), LeaveCC, cond);
- return;
+ Handle<Object> root(isolate()->heap()->roots_array_start()[index],
+ isolate());
+ if (!isolate()->heap()->InNewSpace(*root)) {
+ // The CPU supports fast immediate values, and this root will never
+ // change. We will load it as a relocatable immediate value.
+ mov(destination, Operand(root), LeaveCC, cond);
+ return;
+ }
}
ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
}
@@ -486,7 +489,7 @@ void MacroAssembler::RecordWrite(Register object,
if (emit_debug_code()) {
ldr(ip, MemOperand(address));
cmp(ip, value);
- Check(eq, kWrongAddressOrValuePassedToRecordWrite);
+ Check(eq, "Wrong address or value passed to RecordWrite");
}
Label done;
@@ -1487,7 +1490,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// In debug mode, make sure the lexical context is set.
#ifdef DEBUG
cmp(scratch, Operand::Zero());
- Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
+ Check(ne, "we should not have an empty lexical context");
#endif
// Load the native context of the current context.
@@ -1505,7 +1508,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
LoadRoot(ip, Heap::kNativeContextMapRootIndex);
cmp(holder_reg, ip);
- Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
+ Check(eq, "JSGlobalObject::native_context should be a native context.");
pop(holder_reg); // Restore holder.
}
@@ -1522,12 +1525,12 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
mov(holder_reg, ip); // Move ip to its holding place.
LoadRoot(ip, Heap::kNullValueRootIndex);
cmp(holder_reg, ip);
- Check(ne, kJSGlobalProxyContextShouldNotBeNull);
+ Check(ne, "JSGlobalProxy::context() should not be null.");
ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
LoadRoot(ip, Heap::kNativeContextMapRootIndex);
cmp(holder_reg, ip);
- Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
+ Check(eq, "JSGlobalObject::native_context should be a native context.");
// Restore ip is not needed. ip is reloaded below.
pop(holder_reg); // Restore holder.
// Restore ip to holder's context.
@@ -1724,7 +1727,7 @@ void MacroAssembler::Allocate(int object_size,
// respect to register content between debug and release mode.
ldr(ip, MemOperand(topaddr));
cmp(result, ip);
- Check(eq, kUnexpectedAllocationTop);
+ Check(eq, "Unexpected allocation top");
}
// Load allocation limit into ip. Result already contains allocation top.
ldr(ip, MemOperand(topaddr, limit - top));
@@ -1822,7 +1825,7 @@ void MacroAssembler::Allocate(Register object_size,
// respect to register content between debug and release mode.
ldr(ip, MemOperand(topaddr));
cmp(result, ip);
- Check(eq, kUnexpectedAllocationTop);
+ Check(eq, "Unexpected allocation top");
}
// Load allocation limit into ip. Result already contains allocation top.
ldr(ip, MemOperand(topaddr, limit - top));
@@ -1856,7 +1859,7 @@ void MacroAssembler::Allocate(Register object_size,
// Update allocation top. result temporarily holds the new top.
if (emit_debug_code()) {
tst(scratch2, Operand(kObjectAlignmentMask));
- Check(eq, kUnalignedAllocationInNewSpace);
+ Check(eq, "Unaligned allocation in new space");
}
str(scratch2, MemOperand(topaddr));
@@ -1879,7 +1882,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object,
mov(scratch, Operand(new_space_allocation_top));
ldr(scratch, MemOperand(scratch));
cmp(object, scratch);
- Check(lt, kUndoAllocationOfNonAllocatedMemory);
+ Check(lt, "Undo allocation of non allocated memory");
#endif
// Write the address of the object to un-allocate as the current top.
mov(scratch, Operand(new_space_allocation_top));
@@ -2128,7 +2131,7 @@ void MacroAssembler::StoreNumberToDoubleElements(
if (emit_debug_code()) {
vmrs(ip);
tst(ip, Operand(kVFPDefaultNaNModeControlBit));
- Assert(ne, kDefaultNaNModeNotSet);
+ Assert(ne, "Default NaN mode not set");
}
VFPCanonicalizeNaN(double_scratch);
b(&store);
@@ -2378,7 +2381,7 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
if (emit_debug_code()) {
ldr(r1, MemOperand(r7, kLevelOffset));
cmp(r1, r6);
- Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
+ Check(eq, "Unexpected level after return from api call");
}
sub(r6, r6, Operand(1));
str(r6, MemOperand(r7, kLevelOffset));
@@ -2779,9 +2782,9 @@ void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
}
-void MacroAssembler::Assert(Condition cond, BailoutReason reason) {
+void MacroAssembler::Assert(Condition cond, const char* msg) {
if (emit_debug_code())
- Check(cond, reason);
+ Check(cond, msg);
}
@@ -2800,23 +2803,23 @@ void MacroAssembler::AssertFastElements(Register elements) {
LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
cmp(elements, ip);
b(eq, &ok);
- Abort(kJSObjectWithFastElementsMapHasSlowElements);
+ Abort("JSObject with fast elements map has slow elements");
bind(&ok);
pop(elements);
}
}
-void MacroAssembler::Check(Condition cond, BailoutReason reason) {
+void MacroAssembler::Check(Condition cond, const char* msg) {
Label L;
b(cond, &L);
- Abort(reason);
+ Abort(msg);
// will not return here
bind(&L);
}
-void MacroAssembler::Abort(BailoutReason reason) {
+void MacroAssembler::Abort(const char* msg) {
Label abort_start;
bind(&abort_start);
// We want to pass the msg string like a smi to avoid GC
@@ -2824,7 +2827,6 @@ void MacroAssembler::Abort(BailoutReason reason) {
// properly. Instead, we pass an aligned pointer that is
// a proper v8 smi, but also pass the alignment difference
// from the real pointer as a smi.
- const char* msg = GetBailoutReason(reason);
intptr_t p1 = reinterpret_cast<intptr_t>(msg);
intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
@@ -2967,7 +2969,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
b(&ok);
bind(&fail);
- Abort(kGlobalFunctionsMustHaveInitialMap);
+ Abort("Global functions must have initial map");
bind(&ok);
}
}
@@ -3036,7 +3038,7 @@ void MacroAssembler::AssertNotSmi(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
tst(object, Operand(kSmiTagMask));
- Check(ne, kOperandIsASmi);
+ Check(ne, "Operand is a smi");
}
}
@@ -3045,7 +3047,7 @@ void MacroAssembler::AssertSmi(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
tst(object, Operand(kSmiTagMask));
- Check(eq, kOperandIsNotSmi);
+ Check(eq, "Operand is not smi");
}
}
@@ -3054,12 +3056,12 @@ void MacroAssembler::AssertString(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
tst(object, Operand(kSmiTagMask));
- Check(ne, kOperandIsASmiAndNotAString);
+ Check(ne, "Operand is a smi and not a string");
push(object);
ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
pop(object);
- Check(lo, kOperandIsNotAString);
+ Check(lo, "Operand is not a string");
}
}
@@ -3068,12 +3070,12 @@ void MacroAssembler::AssertName(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
tst(object, Operand(kSmiTagMask));
- Check(ne, kOperandIsASmiAndNotAName);
+ Check(ne, "Operand is a smi and not a name");
push(object);
ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
CompareInstanceType(object, object, LAST_NAME_TYPE);
pop(object);
- Check(le, kOperandIsNotAName);
+ Check(le, "Operand is not a name");
}
}
@@ -3082,7 +3084,7 @@ void MacroAssembler::AssertName(Register object) {
void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
if (emit_debug_code()) {
CompareRoot(reg, index);
- Check(eq, kHeapNumberMapRegisterClobbered);
+ Check(eq, "HeapNumberMap register clobbered.");
}
}
@@ -3228,7 +3230,7 @@ void MacroAssembler::CopyBytes(Register src,
bind(&word_loop);
if (emit_debug_code()) {
tst(src, Operand(kPointerSize - 1));
- Assert(eq, kExpectingAlignmentForCopyBytes);
+ Assert(eq, "Expecting alignment for CopyBytes");
}
cmp(length, Operand(kPointerSize));
b(lt, &byte_loop);
@@ -3492,7 +3494,7 @@ void MacroAssembler::GetRelocatedValueLocation(Register ldr_location,
// Check that the instruction is a ldr reg, [pc + offset] .
and_(result, result, Operand(kLdrPCPattern));
cmp(result, Operand(kLdrPCPattern));
- Check(eq, kTheInstructionToPatchShouldBeALoadFromPc);
+ Check(eq, "The instruction to patch should be a load from pc.");
// Result was clobbered. Restore it.
ldr(result, MemOperand(ldr_location));
}
diff --git a/chromium/v8/src/arm/macro-assembler-arm.h b/chromium/v8/src/arm/macro-assembler-arm.h
index 8b9fa2b2216..38308e5cdef 100644
--- a/chromium/v8/src/arm/macro-assembler-arm.h
+++ b/chromium/v8/src/arm/macro-assembler-arm.h
@@ -144,8 +144,6 @@ class MacroAssembler: public Assembler {
Condition cond = al);
void Call(Label* target);
- void Push(Register src) { push(src); }
- void Pop(Register dst) { pop(dst); }
// Register move. May do nothing if the registers are identical.
void Move(Register dst, Handle<Object> value);
@@ -1138,14 +1136,14 @@ class MacroAssembler: public Assembler {
// Calls Abort(msg) if the condition cond is not satisfied.
// Use --debug_code to enable.
- void Assert(Condition cond, BailoutReason reason);
+ void Assert(Condition cond, const char* msg);
void AssertFastElements(Register elements);
// Like Assert(), but always enabled.
- void Check(Condition cond, BailoutReason reason);
+ void Check(Condition cond, const char* msg);
// Print a message to stdout and abort execution.
- void Abort(BailoutReason msg);
+ void Abort(const char* msg);
// Verify restrictions about code generated in stubs.
void set_generating_stub(bool value) { generating_stub_ = value; }
diff --git a/chromium/v8/src/array-iterator.js b/chromium/v8/src/array-iterator.js
index defd7342ab2..8f1ab47b8a2 100644
--- a/chromium/v8/src/array-iterator.js
+++ b/chromium/v8/src/array-iterator.js
@@ -77,15 +77,16 @@ function ArrayIteratorNext() {
return CreateIteratorResultObject(void 0, true);
}
+ var elementKey = ToString(index);
iterator[arrayIteratorNextIndexSymbol] = index + 1;
if (itemKind == ARRAY_ITERATOR_KIND_VALUES)
- return CreateIteratorResultObject(array[index], false);
+ return CreateIteratorResultObject(array[elementKey], false);
if (itemKind == ARRAY_ITERATOR_KIND_ENTRIES)
- return CreateIteratorResultObject([index, array[index]], false);
+ return CreateIteratorResultObject([elementKey, array[elementKey]], false);
- return CreateIteratorResultObject(index, false);
+ return CreateIteratorResultObject(elementKey, false);
}
function ArrayEntries() {
diff --git a/chromium/v8/src/assert-scope.h b/chromium/v8/src/assert-scope.h
index 269b280d027..13adbd0f9c5 100644
--- a/chromium/v8/src/assert-scope.h
+++ b/chromium/v8/src/assert-scope.h
@@ -41,7 +41,6 @@ enum PerThreadAssertType {
HANDLE_ALLOCATION_ASSERT,
HANDLE_DEREFERENCE_ASSERT,
DEFERRED_HANDLE_DEREFERENCE_ASSERT,
- CODE_DEPENDENCY_CHANGE_ASSERT,
LAST_PER_THREAD_ASSERT_TYPE
};
@@ -171,14 +170,6 @@ typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
AllowDeferredHandleDereference;
-// Scope to document where we do not expect deferred handles to be dereferenced.
-typedef PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>
- DisallowCodeDependencyChange;
-
-// Scope to introduce an exception to DisallowDeferredHandleDereference.
-typedef PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>
- AllowCodeDependencyChange;
-
} } // namespace v8::internal
#endif // V8_ASSERT_SCOPE_H_
diff --git a/chromium/v8/src/ast.cc b/chromium/v8/src/ast.cc
index 23b680d47f4..e0bca67aab1 100644
--- a/chromium/v8/src/ast.cc
+++ b/chromium/v8/src/ast.cc
@@ -273,8 +273,7 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
uint32_t hash = literal->Hash();
// If the key of a computed property is in the table, do not emit
// a store for the property later.
- if ((property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
- property->kind() == ObjectLiteral::Property::COMPUTED) &&
+ if (property->kind() == ObjectLiteral::Property::COMPUTED &&
table.Lookup(literal, hash, false, allocator) != NULL) {
property->set_emit_store(false);
} else {
@@ -305,6 +304,17 @@ void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
}
+bool UnaryOperation::ResultOverwriteAllowed() {
+ switch (op_) {
+ case Token::BIT_NOT:
+ case Token::SUB:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
// TODO(olivf) If this Operation is used in a test context, then the right
// hand side has a ToBoolean stub and we want to collect the type information.
diff --git a/chromium/v8/src/ast.h b/chromium/v8/src/ast.h
index a8b74213adb..f14156f93c6 100644
--- a/chromium/v8/src/ast.h
+++ b/chromium/v8/src/ast.h
@@ -259,7 +259,6 @@ class Statement: public AstNode {
Statement() : statement_pos_(RelocInfo::kNoPosition) {}
bool IsEmpty() { return AsEmptyStatement() != NULL; }
- virtual bool IsJump() const { return false; }
void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
int statement_pos() const { return statement_pos_; }
@@ -292,6 +291,7 @@ class SmallMapList {
}
void Add(Handle<Map> handle, Zone* zone) {
+ ASSERT(!handle->is_deprecated());
list_.Add(handle.location(), zone);
}
@@ -389,7 +389,7 @@ class Expression: public AstNode {
protected:
explicit Expression(Isolate* isolate)
- : bounds_(Bounds::Unbounded(isolate)),
+ : bounds_(Type::None(), Type::Any(), isolate),
id_(GetNextId(isolate)),
test_id_(GetNextId(isolate)) {}
void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
@@ -459,11 +459,6 @@ class Block: public BreakableStatement {
ZoneList<Statement*>* statements() { return &statements_; }
bool is_initializer_block() const { return is_initializer_block_; }
- virtual bool IsJump() const {
- return !statements_.is_empty() && statements_.last()->IsJump()
- && labels() == NULL; // Good enough as an approximation...
- }
-
Scope* scope() const { return scope_; }
void set_scope(Scope* scope) { scope_ = scope; }
@@ -1014,7 +1009,6 @@ class ExpressionStatement: public Statement {
void set_expression(Expression* e) { expression_ = e; }
Expression* expression() const { return expression_; }
- virtual bool IsJump() const { return expression_->IsThrow(); }
protected:
explicit ExpressionStatement(Expression* expression)
@@ -1025,16 +1019,7 @@ class ExpressionStatement: public Statement {
};
-class JumpStatement: public Statement {
- public:
- virtual bool IsJump() const { return true; }
-
- protected:
- JumpStatement() {}
-};
-
-
-class ContinueStatement: public JumpStatement {
+class ContinueStatement: public Statement {
public:
DECLARE_NODE_TYPE(ContinueStatement)
@@ -1049,7 +1034,7 @@ class ContinueStatement: public JumpStatement {
};
-class BreakStatement: public JumpStatement {
+class BreakStatement: public Statement {
public:
DECLARE_NODE_TYPE(BreakStatement)
@@ -1064,7 +1049,7 @@ class BreakStatement: public JumpStatement {
};
-class ReturnStatement: public JumpStatement {
+class ReturnStatement: public Statement {
public:
DECLARE_NODE_TYPE(ReturnStatement)
@@ -1183,11 +1168,6 @@ class IfStatement: public Statement {
Statement* then_statement() const { return then_statement_; }
Statement* else_statement() const { return else_statement_; }
- virtual bool IsJump() const {
- return HasThenStatement() && then_statement()->IsJump()
- && HasElseStatement() && else_statement()->IsJump();
- }
-
BailoutId IfId() const { return if_id_; }
BailoutId ThenId() const { return then_id_; }
BailoutId ElseId() const { return else_id_; }
@@ -1847,6 +1827,8 @@ class UnaryOperation: public Expression {
public:
DECLARE_NODE_TYPE(UnaryOperation)
+ virtual bool ResultOverwriteAllowed();
+
Token::Value op() const { return op_; }
Expression* expression() const { return expression_; }
virtual int position() const { return pos_; }
@@ -1854,6 +1836,8 @@ class UnaryOperation: public Expression {
BailoutId MaterializeTrueId() { return materialize_true_id_; }
BailoutId MaterializeFalseId() { return materialize_false_id_; }
+ TypeFeedbackId UnaryOperationFeedbackId() const { return reuse(id()); }
+
virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
protected:
diff --git a/chromium/v8/src/atomicops_internals_tsan.h b/chromium/v8/src/atomicops_internals_tsan.h
index b5162bad9f6..e52c26c2fe2 100644
--- a/chromium/v8/src/atomicops_internals_tsan.h
+++ b/chromium/v8/src/atomicops_internals_tsan.h
@@ -32,12 +32,6 @@
#ifndef V8_ATOMICOPS_INTERNALS_TSAN_H_
#define V8_ATOMICOPS_INTERNALS_TSAN_H_
-namespace v8 {
-namespace internal {
-
-#ifndef TSAN_INTERFACE_ATOMIC_H
-#define TSAN_INTERFACE_ATOMIC_H
-
// This struct is not part of the public API of this module; clients may not
// use it. (However, it's exported via BASE_EXPORT because clients implicitly
// do use it at link time by inlining these functions.)
@@ -53,6 +47,12 @@ extern struct AtomicOps_x86CPUFeatureStruct
#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+namespace v8 {
+namespace internal {
+
+#ifndef TSAN_INTERFACE_ATOMIC_H
+#define TSAN_INTERFACE_ATOMIC_H
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/chromium/v8/src/bootstrapper.cc b/chromium/v8/src/bootstrapper.cc
index 2a385aa4865..c2cc6efc45f 100644
--- a/chromium/v8/src/bootstrapper.cc
+++ b/chromium/v8/src/bootstrapper.cc
@@ -2085,11 +2085,6 @@ bool Genesis::InstallExperimentalNatives() {
"native harmony-string.js") == 0) {
if (!CompileExperimentalBuiltin(isolate(), i)) return false;
}
- if (FLAG_harmony_arrays &&
- strcmp(ExperimentalNatives::GetScriptName(i).start(),
- "native harmony-array.js") == 0) {
- if (!CompileExperimentalBuiltin(isolate(), i)) return false;
- }
}
InstallExperimentalNativeFunctions();
diff --git a/chromium/v8/src/builtins.h b/chromium/v8/src/builtins.h
index bb36c0251d9..73a2e964590 100644
--- a/chromium/v8/src/builtins.h
+++ b/chromium/v8/src/builtins.h
@@ -259,6 +259,8 @@ enum BuiltinExtraArguments {
V(BIT_OR, 1) \
V(BIT_AND, 1) \
V(BIT_XOR, 1) \
+ V(UNARY_MINUS, 0) \
+ V(BIT_NOT, 0) \
V(SHL, 1) \
V(SAR, 1) \
V(SHR, 1) \
diff --git a/chromium/v8/src/code-stubs-hydrogen.cc b/chromium/v8/src/code-stubs-hydrogen.cc
index 4f6db35dd93..9ca6a47f2ee 100644
--- a/chromium/v8/src/code-stubs-hydrogen.cc
+++ b/chromium/v8/src/code-stubs-hydrogen.cc
@@ -41,13 +41,13 @@ static LChunk* OptimizeGraph(HGraph* graph) {
DisallowHandleDereference no_deref;
ASSERT(graph != NULL);
- BailoutReason bailout_reason = kNoReason;
+ SmartArrayPointer<char> bailout_reason;
if (!graph->Optimize(&bailout_reason)) {
- FATAL(GetBailoutReason(bailout_reason));
+ FATAL(bailout_reason.is_empty() ? "unknown" : *bailout_reason);
}
LChunk* chunk = LChunk::NewChunk(graph);
if (chunk == NULL) {
- FATAL(GetBailoutReason(graph->info()->bailout_reason()));
+ FATAL(graph->info()->bailout_reason());
}
return chunk;
}
@@ -92,7 +92,7 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
}
~ArrayContextChecker() {
- checker_.ElseDeopt("Array constructor called from different context");
+ checker_.ElseDeopt();
checker_.End();
}
private:
@@ -233,7 +233,7 @@ class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
IfBuilder builder(this);
builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
builder.Then();
- builder.ElseDeopt("Forced deopt to runtime");
+ builder.ElseDeopt();
return undefined;
}
@@ -387,7 +387,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
length));
}
- checker.ElseDeopt("Uninitialized boilerplate literals");
+ checker.ElseDeopt();
checker.End();
return environment()->Pop();
@@ -434,7 +434,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
}
environment()->Push(object);
- checker.ElseDeopt("Uninitialized boilerplate in fast clone");
+ checker.ElseDeopt();
checker.End();
return environment()->Pop();
@@ -802,6 +802,44 @@ Handle<Code> CompareNilICStub::GenerateCode() {
template <>
+HValue* CodeStubGraphBuilder<UnaryOpStub>::BuildCodeInitializedStub() {
+ UnaryOpStub* stub = casted_stub();
+ Handle<Type> type = stub->GetType(graph()->isolate());
+ HValue* input = GetParameter(0);
+
+ // Prevent unwanted HChange being inserted to ensure that the stub
+ // deopts on newly encountered types.
+ if (!type->Maybe(Type::Double())) {
+ input = Add<HForceRepresentation>(input, Representation::Smi());
+ }
+
+ if (!type->Is(Type::Number())) {
+ // If we expect to see other things than Numbers, we will create a generic
+ // stub, which handles all numbers and calls into the runtime for the rest.
+ IfBuilder if_number(this);
+ if_number.If<HIsNumberAndBranch>(input);
+ if_number.Then();
+ HInstruction* res = BuildUnaryMathOp(input, type, stub->operation());
+ if_number.Return(AddInstruction(res));
+ if_number.Else();
+ HValue* function = AddLoadJSBuiltin(stub->ToJSBuiltin());
+ Add<HPushArgument>(GetParameter(0));
+ HValue* result = Add<HInvokeFunction>(function, 1);
+ if_number.Return(result);
+ if_number.End();
+ return graph()->GetConstantUndefined();
+ }
+
+ return AddInstruction(BuildUnaryMathOp(input, type, stub->operation()));
+}
+
+
+Handle<Code> UnaryOpStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
+template <>
HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
ToBooleanStub* stub = casted_stub();
@@ -844,7 +882,7 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
IfBuilder builder(this);
builder.If<HCompareObjectEqAndBranch>(cell_contents, value);
builder.Then();
- builder.ElseDeopt("Unexpected cell contents in constant global store");
+ builder.ElseDeopt();
builder.End();
} else {
// Load the payload of the global parameter cell. A hole indicates that the
@@ -854,7 +892,7 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
HValue* hole_value = Add<HConstant>(hole);
builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
builder.Then();
- builder.Deopt("Unexpected cell contents in global store");
+ builder.Deopt();
builder.Else();
Add<HStoreNamedField>(cell, access, value);
builder.End();
@@ -878,8 +916,7 @@ HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() {
if (FLAG_trace_elements_transitions) {
// Tracing elements transitions is the job of the runtime.
- Add<HDeoptimize>("Deopt due to --trace-elements-transitions",
- Deoptimizer::EAGER);
+ Add<HDeoptimize>(Deoptimizer::EAGER);
} else {
info()->MarkAsSavesCallerDoubles();
diff --git a/chromium/v8/src/code-stubs.cc b/chromium/v8/src/code-stubs.cc
index f656bf7d96b..5f6616ea07a 100644
--- a/chromium/v8/src/code-stubs.cc
+++ b/chromium/v8/src/code-stubs.cc
@@ -204,6 +204,71 @@ void CodeStub::PrintName(StringStream* stream) {
}
+Builtins::JavaScript UnaryOpStub::ToJSBuiltin() {
+ switch (operation_) {
+ default:
+ UNREACHABLE();
+ case Token::SUB:
+ return Builtins::UNARY_MINUS;
+ case Token::BIT_NOT:
+ return Builtins::BIT_NOT;
+ }
+}
+
+
+Handle<JSFunction> UnaryOpStub::ToJSFunction(Isolate* isolate) {
+ Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
+ Object* builtin = builtins->javascript_builtin(ToJSBuiltin());
+ return Handle<JSFunction>(JSFunction::cast(builtin), isolate);
+}
+
+
+MaybeObject* UnaryOpStub::Result(Handle<Object> object, Isolate* isolate) {
+ Handle<JSFunction> builtin_function = ToJSFunction(isolate);
+ bool caught_exception;
+ Handle<Object> result = Execution::Call(builtin_function, object,
+ 0, NULL, &caught_exception);
+ if (caught_exception) {
+ return Failure::Exception();
+ }
+ return *result;
+}
+
+
+void UnaryOpStub::UpdateStatus(Handle<Object> object) {
+ State old_state(state_);
+ if (object->IsSmi()) {
+ state_.Add(SMI);
+ if (operation_ == Token::SUB && *object == 0) {
+ // The result (-0) has to be represented as double.
+ state_.Add(HEAP_NUMBER);
+ }
+ } else if (object->IsHeapNumber()) {
+ state_.Add(HEAP_NUMBER);
+ } else {
+ state_.Add(GENERIC);
+ }
+ TraceTransition(old_state, state_);
+}
+
+
+Handle<Type> UnaryOpStub::GetType(Isolate* isolate) {
+ if (state_.Contains(GENERIC)) {
+ return handle(Type::Any(), isolate);
+ }
+ Handle<Type> type = handle(Type::None(), isolate);
+ if (state_.Contains(SMI)) {
+ type = handle(
+ Type::Union(type, handle(Type::Smi(), isolate)), isolate);
+ }
+ if (state_.Contains(HEAP_NUMBER)) {
+ type = handle(
+ Type::Union(type, handle(Type::Double(), isolate)), isolate);
+ }
+ return type;
+}
+
+
void BinaryOpStub::Generate(MacroAssembler* masm) {
// Explicitly allow generation of nested stubs. It is safe here because
// generation code does not use any raw pointers.
@@ -289,6 +354,29 @@ void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
#undef __
+void UnaryOpStub::PrintBaseName(StringStream* stream) {
+ CodeStub::PrintBaseName(stream);
+ if (operation_ == Token::SUB) stream->Add("Minus");
+ if (operation_ == Token::BIT_NOT) stream->Add("Not");
+}
+
+
+void UnaryOpStub::PrintState(StringStream* stream) {
+ state_.Print(stream);
+}
+
+
+void UnaryOpStub::State::Print(StringStream* stream) const {
+ stream->Add("(");
+ SimpleListPrinter printer(stream);
+ if (IsEmpty()) printer.Add("None");
+ if (Contains(GENERIC)) printer.Add("Generic");
+ if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
+ if (Contains(SMI)) printer.Add("Smi");
+ stream->Add(")");
+}
+
+
void BinaryOpStub::PrintName(StringStream* stream) {
const char* op_name = Token::Name(op_);
const char* overwrite_name;
@@ -469,9 +557,6 @@ void CompareNilICStub::UpdateStatus(Handle<Object> object) {
template<class StateType>
void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
- // Note: Although a no-op transition is semantically OK, it is hinting at a
- // bug somewhere in our state transition machinery.
- ASSERT(from != to);
#ifdef DEBUG
if (!FLAG_trace_ic) return;
char buffer[100];
diff --git a/chromium/v8/src/code-stubs.h b/chromium/v8/src/code-stubs.h
index c58acd6b16d..84d9b023b3a 100644
--- a/chromium/v8/src/code-stubs.h
+++ b/chromium/v8/src/code-stubs.h
@@ -40,6 +40,7 @@ namespace internal {
#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
V(CallFunction) \
V(CallConstruct) \
+ V(UnaryOp) \
V(BinaryOp) \
V(StringAdd) \
V(SubString) \
@@ -592,6 +593,73 @@ class StoreGlobalStub : public HydrogenCodeStub {
};
+class UnaryOpStub : public HydrogenCodeStub {
+ public:
+ // Stub without type info available -> construct uninitialized
+ explicit UnaryOpStub(Token::Value operation)
+ : HydrogenCodeStub(UNINITIALIZED), operation_(operation) { }
+ explicit UnaryOpStub(Code::ExtraICState ic_state) :
+ state_(StateBits::decode(ic_state)),
+ operation_(OperatorBits::decode(ic_state)) { }
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
+ virtual InlineCacheState GetICState() {
+ if (state_.Contains(GENERIC)) {
+ return MEGAMORPHIC;
+ } else if (state_.IsEmpty()) {
+ return PREMONOMORPHIC;
+ } else {
+ return MONOMORPHIC;
+ }
+ }
+ virtual Code::ExtraICState GetExtraICState() {
+ return OperatorBits::encode(operation_) |
+ StateBits::encode(state_.ToIntegral());
+ }
+
+ Token::Value operation() { return operation_; }
+ Handle<JSFunction> ToJSFunction(Isolate* isolate);
+ Builtins::JavaScript ToJSBuiltin();
+
+ void UpdateStatus(Handle<Object> object);
+ MaybeObject* Result(Handle<Object> object, Isolate* isolate);
+ Handle<Code> GenerateCode();
+ Handle<Type> GetType(Isolate* isolate);
+
+ protected:
+ void PrintState(StringStream* stream);
+ void PrintBaseName(StringStream* stream);
+
+ private:
+ enum UnaryOpType {
+ SMI,
+ HEAP_NUMBER,
+ GENERIC,
+ NUMBER_OF_TYPES
+ };
+
+ class State : public EnumSet<UnaryOpType, byte> {
+ public:
+ State() : EnumSet<UnaryOpType, byte>() { }
+ explicit State(byte bits) : EnumSet<UnaryOpType, byte>(bits) { }
+ void Print(StringStream* stream) const;
+ };
+
+ class StateBits : public BitField<int, 0, NUMBER_OF_TYPES> { };
+ class OperatorBits : public BitField<Token::Value, NUMBER_OF_TYPES, 8> { };
+
+ State state_;
+ Token::Value operation_;
+
+ virtual CodeStub::Major MajorKey() { return UnaryOp; }
+ virtual int NotMissMinorKey() { return GetExtraICState(); }
+};
+
+
class FastCloneShallowArrayStub : public HydrogenCodeStub {
public:
// Maximum length of copied elements array.
diff --git a/chromium/v8/src/compiler.cc b/chromium/v8/src/compiler.cc
index f6e5daac854..3c51baa30e9 100644
--- a/chromium/v8/src/compiler.cc
+++ b/chromium/v8/src/compiler.cc
@@ -120,7 +120,6 @@ void CompilationInfo::Initialize(Isolate* isolate,
return;
}
mode_ = V8::UseCrankshaft() ? mode : NONOPT;
- abort_due_to_dependency_ = false;
if (script_->type()->value() == Script::TYPE_NATIVE) {
MarkAsNative();
}
@@ -128,7 +127,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
ASSERT(language_mode() == CLASSIC_MODE);
SetLanguageMode(shared_info_->language_mode());
}
- set_bailout_reason(kUnknown);
+ set_bailout_reason("unknown");
}
@@ -343,7 +342,7 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
const int kMaxOptCount =
FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
if (info()->opt_count() > kMaxOptCount) {
- info()->set_bailout_reason(kOptimizedTooManyTimes);
+ info()->set_bailout_reason("optimized too many times");
return AbortOptimization();
}
@@ -357,14 +356,14 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
Scope* scope = info()->scope();
if ((scope->num_parameters() + 1) > parameter_limit) {
- info()->set_bailout_reason(kTooManyParameters);
+ info()->set_bailout_reason("too many parameters");
return AbortOptimization();
}
const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
if (!info()->osr_ast_id().IsNone() &&
scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
- info()->set_bailout_reason(kTooManyParametersLocals);
+ info()->set_bailout_reason("too many parameters/locals");
return AbortOptimization();
}
@@ -447,12 +446,6 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
}
}
- if (info()->HasAbortedDueToDependencyChange()) {
- info_->set_bailout_reason(kBailedOutDueToDependencyChange);
- info_->AbortOptimization();
- return SetLastStatus(BAILED_OUT);
- }
-
return SetLastStatus(SUCCEEDED);
}
@@ -461,14 +454,13 @@ OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
- DisallowCodeDependencyChange no_dependency_change;
ASSERT(last_status() == SUCCEEDED);
Timer t(this, &time_taken_to_optimize_);
ASSERT(graph_ != NULL);
- BailoutReason bailout_reason = kNoReason;
+ SmartArrayPointer<char> bailout_reason;
if (!graph_->Optimize(&bailout_reason)) {
- if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason);
+ if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
return SetLastStatus(BAILED_OUT);
} else {
chunk_ = LChunk::NewChunk(graph_);
@@ -482,8 +474,6 @@ OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
ASSERT(last_status() == SUCCEEDED);
- ASSERT(!info()->HasAbortedDueToDependencyChange());
- DisallowCodeDependencyChange no_dependency_change;
{ // Scope for timer.
Timer timer(this, &time_taken_to_codegen_);
ASSERT(chunk_ != NULL);
@@ -495,9 +485,7 @@ OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
DisallowDeferredHandleDereference no_deferred_handle_deref;
Handle<Code> optimized_code = chunk_->Codegen();
if (optimized_code.is_null()) {
- if (info()->bailout_reason() == kNoReason) {
- info()->set_bailout_reason(kCodeGenerationFailed);
- }
+ info()->set_bailout_reason("code generation failed");
return AbortOptimization();
}
info()->SetCode(optimized_code);
@@ -792,7 +780,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
if (!result.is_null()) {
// Explicitly disable optimization for eval code. We're not yet prepared
// to handle eval-code in the optimizing compiler.
- result->DisableOptimization(kEval);
+ result->DisableOptimization("eval");
// If caller is strict mode, the result must be in strict mode or
// extended mode as well, but not the other way around. Consider:
@@ -825,7 +813,6 @@ static bool InstallFullCode(CompilationInfo* info) {
// was flushed. By setting the code object last we avoid this.
Handle<SharedFunctionInfo> shared = info->shared_info();
Handle<Code> code = info->code();
- CHECK(code->kind() == Code::FUNCTION);
Handle<JSFunction> function = info->closure();
Handle<ScopeInfo> scope_info =
ScopeInfo::Create(info->scope(), info->zone());
@@ -983,9 +970,7 @@ void Compiler::RecompileParallel(Handle<JSFunction> closure) {
if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
if (FLAG_trace_parallel_recompilation) {
- PrintF(" ** Compilation queue full, will retry optimizing ");
- closure->PrintName();
- PrintF(" on next run.\n");
+ PrintF(" ** Compilation queue, will retry opting on next run.\n");
}
return;
}
@@ -1070,13 +1055,13 @@ void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
// the unoptimized code.
OptimizingCompiler::Status status = optimizing_compiler->last_status();
if (info->HasAbortedDueToDependencyChange()) {
- info->set_bailout_reason(kBailedOutDueToDependencyChange);
+ info->set_bailout_reason("bailed out due to dependent map");
status = optimizing_compiler->AbortOptimization();
} else if (status != OptimizingCompiler::SUCCEEDED) {
- info->set_bailout_reason(kFailedBailedOutLastTime);
+ info->set_bailout_reason("failed/bailed out last time");
status = optimizing_compiler->AbortOptimization();
} else if (isolate->DebuggerHasBreakPoints()) {
- info->set_bailout_reason(kDebuggerIsActive);
+ info->set_bailout_reason("debugger is active");
status = optimizing_compiler->AbortOptimization();
} else {
status = optimizing_compiler->GenerateAndInstallCode();
diff --git a/chromium/v8/src/compiler.h b/chromium/v8/src/compiler.h
index 7d442f9d461..d36e488b174 100644
--- a/chromium/v8/src/compiler.h
+++ b/chromium/v8/src/compiler.h
@@ -199,11 +199,6 @@ class CompilationInfo {
return IsCompilingForDebugging::decode(flags_);
}
- bool ShouldTrapOnDeopt() const {
- return (FLAG_trap_on_deopt && IsOptimizing()) ||
- (FLAG_trap_on_stub_deopt && IsStub());
- }
-
bool has_global_object() const {
return !closure().is_null() &&
(closure()->context()->global_object() != NULL);
@@ -263,8 +258,8 @@ class CompilationInfo {
SaveHandle(&script_);
}
- BailoutReason bailout_reason() const { return bailout_reason_; }
- void set_bailout_reason(BailoutReason reason) { bailout_reason_ = reason; }
+ const char* bailout_reason() const { return bailout_reason_; }
+ void set_bailout_reason(const char* reason) { bailout_reason_ = reason; }
int prologue_offset() const {
ASSERT_NE(kPrologueOffsetNotSet, prologue_offset_);
@@ -298,13 +293,11 @@ class CompilationInfo {
}
void AbortDueToDependencyChange() {
- ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
- abort_due_to_dependency_ = true;
+ mode_ = DEPENDENCY_CHANGE_ABORT;
}
bool HasAbortedDueToDependencyChange() {
- ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
- return abort_due_to_dependency_;
+ return mode_ == DEPENDENCY_CHANGE_ABORT;
}
protected:
@@ -328,7 +321,8 @@ class CompilationInfo {
BASE,
OPTIMIZE,
NONOPT,
- STUB
+ STUB,
+ DEPENDENCY_CHANGE_ABORT
};
void Initialize(Isolate* isolate, Mode mode, Zone* zone);
@@ -402,9 +396,6 @@ class CompilationInfo {
Mode mode_;
BailoutId osr_ast_id_;
- // Flag whether compilation needs to be aborted due to dependency change.
- bool abort_due_to_dependency_;
-
// The zone from which the compilation pipeline working on this
// CompilationInfo allocates.
Zone* zone_;
@@ -421,7 +412,7 @@ class CompilationInfo {
}
}
- BailoutReason bailout_reason_;
+ const char* bailout_reason_;
int prologue_offset_;
diff --git a/chromium/v8/src/cpu-profiler.cc b/chromium/v8/src/cpu-profiler.cc
index 747542f7378..0a83b85f505 100644
--- a/chromium/v8/src/cpu-profiler.cc
+++ b/chromium/v8/src/cpu-profiler.cc
@@ -106,7 +106,7 @@ bool ProfilerEventsProcessor::ProcessCodeEvent() {
bool ProfilerEventsProcessor::ProcessTicks() {
while (true) {
- while (!ticks_from_vm_buffer_.IsEmpty()
+ if (!ticks_from_vm_buffer_.IsEmpty()
&& ticks_from_vm_buffer_.Peek()->order ==
last_processed_code_event_id_) {
TickSampleEventRecord record;
diff --git a/chromium/v8/src/cpu-profiler.h b/chromium/v8/src/cpu-profiler.h
index 1dd405e5d76..cbe3e3cf81d 100644
--- a/chromium/v8/src/cpu-profiler.h
+++ b/chromium/v8/src/cpu-profiler.h
@@ -241,7 +241,6 @@ class CpuProfiler : public CodeEventListener {
ProfileGenerator* generator() const { return generator_; }
ProfilerEventsProcessor* processor() const { return processor_; }
- Isolate* isolate() const { return isolate_; }
private:
void StartProcessorIfNotStarted();
@@ -259,6 +258,7 @@ class CpuProfiler : public CodeEventListener {
bool need_to_stop_sampler_;
bool is_profiling_;
+ private:
DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
};
diff --git a/chromium/v8/src/d8.cc b/chromium/v8/src/d8.cc
index c7b66c2a150..6e7beebf549 100644
--- a/chromium/v8/src/d8.cc
+++ b/chromium/v8/src/d8.cc
@@ -1406,14 +1406,6 @@ bool Shell::SetOptions(int argc, char* argv[]) {
#else
options.num_parallel_files++;
#endif // V8_SHARED
- } else if (strcmp(argv[i], "--dump-heap-constants") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support constant dumping\n");
- return false;
-#else
- options.dump_heap_constants = true;
- argv[i] = NULL;
-#endif
}
#ifdef V8_SHARED
else if (strcmp(argv[i], "--dump-counters") == 0) {
@@ -1568,63 +1560,6 @@ static void SetStandaloneFlagsViaCommandLine() {
#endif
-#ifndef V8_SHARED
-static void DumpHeapConstants(i::Isolate* isolate) {
- i::Heap* heap = isolate->heap();
-
- // Dump the INSTANCE_TYPES table to the console.
- printf("# List of known V8 instance types.\n");
-#define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
- printf("INSTANCE_TYPES = {\n");
- INSTANCE_TYPE_LIST(DUMP_TYPE)
- printf("}\n");
-#undef DUMP_TYPE
-
- // Dump the KNOWN_MAP table to the console.
- printf("\n# List of known V8 maps.\n");
-#define ROOT_LIST_CASE(type, name, camel_name) \
- if (n == NULL && o == heap->name()) n = #camel_name;
-#define STRUCT_LIST_CASE(upper_name, camel_name, name) \
- if (n == NULL && o == heap->name##_map()) n = #camel_name "Map";
- i::HeapObjectIterator it(heap->map_space());
- printf("KNOWN_MAPS = {\n");
- for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
- i::Map* m = i::Map::cast(o);
- const char* n = NULL;
- intptr_t p = reinterpret_cast<intptr_t>(m) & 0xfffff;
- int t = m->instance_type();
- ROOT_LIST(ROOT_LIST_CASE)
- STRUCT_LIST(STRUCT_LIST_CASE)
- if (n == NULL) continue;
- printf(" 0x%05" V8PRIxPTR ": (%d, \"%s\"),\n", p, t, n);
- }
- printf("}\n");
-#undef STRUCT_LIST_CASE
-#undef ROOT_LIST_CASE
-
- // Dump the KNOWN_OBJECTS table to the console.
- printf("\n# List of known V8 objects.\n");
-#define ROOT_LIST_CASE(type, name, camel_name) \
- if (n == NULL && o == heap->name()) n = #camel_name;
- i::OldSpaces spit(heap);
- printf("KNOWN_OBJECTS = {\n");
- for (i::PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
- i::HeapObjectIterator it(s);
- const char* sname = AllocationSpaceName(s->identity());
- for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
- const char* n = NULL;
- intptr_t p = reinterpret_cast<intptr_t>(o) & 0xfffff;
- ROOT_LIST(ROOT_LIST_CASE)
- if (n == NULL) continue;
- printf(" (\"%s\", 0x%05" V8PRIxPTR "): \"%s\",\n", sname, p, n);
- }
- }
- printf("}\n");
-#undef ROOT_LIST_CASE
-}
-#endif // V8_SHARED
-
-
class ShellArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
virtual void* Allocate(size_t length) {
@@ -1668,13 +1603,6 @@ int Shell::Main(int argc, char* argv[]) {
PerIsolateData data(isolate);
InitializeDebugger(isolate);
-#ifndef V8_SHARED
- if (options.dump_heap_constants) {
- DumpHeapConstants(reinterpret_cast<i::Isolate*>(isolate));
- return 0;
- }
-#endif
-
if (options.stress_opt || options.stress_deopt) {
Testing::SetStressRunType(options.stress_opt
? Testing::kStressTypeOpt
diff --git a/chromium/v8/src/d8.h b/chromium/v8/src/d8.h
index 3b06985ca25..4f04342cf4d 100644
--- a/chromium/v8/src/d8.h
+++ b/chromium/v8/src/d8.h
@@ -231,7 +231,6 @@ class ShellOptions {
stress_deopt(false),
interactive_shell(false),
test_shell(false),
- dump_heap_constants(false),
num_isolates(1),
isolate_sources(NULL) { }
@@ -255,7 +254,6 @@ class ShellOptions {
bool stress_deopt;
bool interactive_shell;
bool test_shell;
- bool dump_heap_constants;
int num_isolates;
SourceGroup* isolate_sources;
};
diff --git a/chromium/v8/src/debug.cc b/chromium/v8/src/debug.cc
index 4966713baab..a0b9884410f 100644
--- a/chromium/v8/src/debug.cc
+++ b/chromium/v8/src/debug.cc
@@ -159,6 +159,7 @@ void BreakLocationIterator::Next() {
Code* code = Code::GetCodeFromTargetAddress(target);
if ((code->is_inline_cache_stub() &&
!code->is_binary_op_stub() &&
+ !code->is_unary_op_stub() &&
!code->is_compare_ic_stub() &&
!code->is_to_boolean_ic_stub()) ||
RelocInfo::IsConstructCall(rmode())) {
@@ -409,9 +410,6 @@ bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
HandleScope scope(debug_info_->GetIsolate());
Address target = rinfo()->target_address();
Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
- if (target_code->kind() == Code::STUB) {
- return target_code->major_key() == CodeStub::CallFunction;
- }
return target_code->is_call_stub() || target_code->is_keyed_call_stub();
} else {
return false;
@@ -2047,10 +2045,6 @@ void Debug::PrepareForBreakPoints() {
// If preparing for the first break point make sure to deoptimize all
// functions as debugging does not work with optimized code.
if (!has_break_points_) {
- if (FLAG_parallel_recompilation) {
- isolate_->optimizing_compiler_thread()->Flush();
- }
-
Deoptimizer::DeoptimizeAll(isolate_);
Handle<Code> lazy_compile =
diff --git a/chromium/v8/src/deoptimizer.cc b/chromium/v8/src/deoptimizer.cc
index dc9ffc51186..53b9b76377f 100644
--- a/chromium/v8/src/deoptimizer.cc
+++ b/chromium/v8/src/deoptimizer.cc
@@ -602,12 +602,6 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
deferred_objects_double_values_(0),
deferred_objects_(0),
deferred_heap_numbers_(0),
- jsframe_functions_(0),
- jsframe_has_adapted_arguments_(0),
- materialized_values_(NULL),
- materialized_objects_(NULL),
- materialization_value_index_(0),
- materialization_object_index_(0),
trace_(false) {
// For COMPILED_STUBs called from builtins, the function pointer is a SMI
// indicating an internal frame.
@@ -1214,15 +1208,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
unsigned output_offset = output_frame_size;
for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize;
- int deferred_object_index = deferred_objects_.length();
DoTranslateCommand(iterator, frame_index, output_offset);
- // The allocated receiver of a construct stub frame is passed as the
- // receiver parameter through the translation. It might be encoding
- // a captured object, patch the slot address for a captured object.
- if (i == 0 && deferred_objects_.length() > deferred_object_index) {
- ASSERT(!deferred_objects_[deferred_object_index].is_arguments());
- deferred_objects_[deferred_object_index].patch_slot_address(top_address);
- }
}
// Read caller's PC from the previous frame.
@@ -1647,93 +1633,9 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
}
-Handle<Object> Deoptimizer::MaterializeNextHeapObject() {
- int object_index = materialization_object_index_++;
- ObjectMaterializationDescriptor desc = deferred_objects_[object_index];
- const int length = desc.object_length();
-
- if (desc.duplicate_object() >= 0) {
- // Found a previously materialized object by de-duplication.
- object_index = desc.duplicate_object();
- materialized_objects_->Add(Handle<Object>());
- } else if (desc.is_arguments() && ArgumentsObjectIsAdapted(object_index)) {
- // Use the arguments adapter frame we just built to materialize the
- // arguments object. FunctionGetArguments can't throw an exception.
- Handle<JSFunction> function = ArgumentsObjectFunction(object_index);
- Handle<JSObject> arguments = Handle<JSObject>::cast(
- Accessors::FunctionGetArguments(function));
- materialized_objects_->Add(arguments);
- materialization_value_index_ += length;
- } else if (desc.is_arguments()) {
- // Construct an arguments object and copy the parameters to a newly
- // allocated arguments object backing store.
- Handle<JSFunction> function = ArgumentsObjectFunction(object_index);
- Handle<JSObject> arguments =
- isolate_->factory()->NewArgumentsObject(function, length);
- Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
- ASSERT(array->length() == length);
- arguments->set_elements(*array);
- materialized_objects_->Add(arguments);
- for (int i = 0; i < length; ++i) {
- Handle<Object> value = MaterializeNextValue();
- array->set(i, *value);
- }
- } else {
- // Dispatch on the instance type of the object to be materialized.
- Handle<Map> map = Handle<Map>::cast(MaterializeNextValue());
- switch (map->instance_type()) {
- case HEAP_NUMBER_TYPE: {
- Handle<HeapNumber> number =
- Handle<HeapNumber>::cast(MaterializeNextValue());
- materialized_objects_->Add(number);
- materialization_value_index_ += kDoubleSize / kPointerSize - 1;
- break;
- }
- case JS_OBJECT_TYPE: {
- Handle<JSObject> object =
- isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
- materialized_objects_->Add(object);
- Handle<Object> properties = MaterializeNextValue();
- Handle<Object> elements = MaterializeNextValue();
- object->set_properties(FixedArray::cast(*properties));
- object->set_elements(FixedArray::cast(*elements));
- for (int i = 0; i < length - 3; ++i) {
- Handle<Object> value = MaterializeNextValue();
- object->FastPropertyAtPut(i, *value);
- }
- break;
- }
- default:
- PrintF("[couldn't handle instance type %d]\n", map->instance_type());
- UNREACHABLE();
- }
- }
-
- return materialized_objects_->at(object_index);
-}
-
-
-Handle<Object> Deoptimizer::MaterializeNextValue() {
- int value_index = materialization_value_index_++;
- Handle<Object> value = materialized_values_->at(value_index);
- if (*value == isolate_->heap()->arguments_marker()) {
- value = MaterializeNextHeapObject();
- }
- return value;
-}
-
-
void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
ASSERT_NE(DEBUGGER, bailout_type_);
- // Walk all JavaScript output frames with the given frame iterator.
- for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
- if (frame_index != 0) it->Advance();
- JavaScriptFrame* frame = it->frame();
- jsframe_functions_.Add(handle(frame->function(), isolate_));
- jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments());
- }
-
// Handlify all tagged object values before triggering any allocation.
List<Handle<Object> > values(deferred_objects_tagged_values_.length());
for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
@@ -1750,7 +1652,7 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
Handle<Object> num = isolate_->factory()->NewNumber(d.value());
if (trace_) {
- PrintF("Materialized a new heap number %p [%e] in slot %p\n",
+ PrintF("Materializing a new heap number %p [%e] in slot %p\n",
reinterpret_cast<void*>(*num),
d.value(),
d.slot_address());
@@ -1758,52 +1660,62 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
Memory::Object_at(d.slot_address()) = *num;
}
- // Materialize all heap numbers required for arguments/captured objects.
+ // Materialize all heap numbers required for arguments objects.
for (int i = 0; i < values.length(); i++) {
if (!values.at(i)->IsTheHole()) continue;
double double_value = deferred_objects_double_values_[i];
Handle<Object> num = isolate_->factory()->NewNumber(double_value);
if (trace_) {
- PrintF("Materialized a new heap number %p [%e] for object\n",
+ PrintF("Materializing a new heap number %p [%e] for arguments object\n",
reinterpret_cast<void*>(*num), double_value);
}
values.Set(i, num);
}
- // Materialize arguments/captured objects.
- if (!deferred_objects_.is_empty()) {
- List<Handle<Object> > materialized_objects(deferred_objects_.length());
- materialized_objects_ = &materialized_objects;
- materialized_values_ = &values;
-
- while (materialization_object_index_ < deferred_objects_.length()) {
- int object_index = materialization_object_index_;
- ObjectMaterializationDescriptor descriptor =
- deferred_objects_.at(object_index);
-
- // Find a previously materialized object by de-duplication or
- // materialize a new instance of the object if necessary. Store
- // the materialized object into the frame slot.
- Handle<Object> object = MaterializeNextHeapObject();
- Memory::Object_at(descriptor.slot_address()) = *object;
- if (trace_) {
- if (descriptor.is_arguments()) {
- PrintF("Materialized %sarguments object of length %d for %p: ",
- ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "",
- Handle<JSObject>::cast(object)->elements()->length(),
- reinterpret_cast<void*>(descriptor.slot_address()));
- } else {
- PrintF("Materialized captured object of size %d for %p: ",
- Handle<HeapObject>::cast(object)->Size(),
+ // Materialize arguments objects one frame at a time.
+ for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
+ if (frame_index != 0) it->Advance();
+ JavaScriptFrame* frame = it->frame();
+ Handle<JSFunction> function(frame->function(), isolate_);
+ Handle<JSObject> arguments;
+ for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
+ if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) {
+ ObjectMaterializationDescriptor descriptor =
+ deferred_objects_.RemoveLast();
+ const int length = descriptor.object_length();
+ if (arguments.is_null()) {
+ if (frame->has_adapted_arguments()) {
+ // Use the arguments adapter frame we just built to materialize the
+ // arguments object. FunctionGetArguments can't throw an exception.
+ arguments = Handle<JSObject>::cast(
+ Accessors::FunctionGetArguments(function));
+ values.RewindBy(length);
+ } else {
+ // Construct an arguments object and copy the parameters to a newly
+ // allocated arguments object backing store.
+ arguments =
+ isolate_->factory()->NewArgumentsObject(function, length);
+ Handle<FixedArray> array =
+ isolate_->factory()->NewFixedArray(length);
+ ASSERT(array->length() == length);
+ for (int i = length - 1; i >= 0 ; --i) {
+ array->set(i, *values.RemoveLast());
+ }
+ arguments->set_elements(*array);
+ }
+ }
+ frame->SetExpression(i, *arguments);
+ ASSERT_EQ(Memory::Object_at(descriptor.slot_address()), *arguments);
+ if (trace_) {
+ PrintF("Materializing %sarguments object of length %d for %p: ",
+ frame->has_adapted_arguments() ? "(adapted) " : "",
+ arguments->elements()->length(),
reinterpret_cast<void*>(descriptor.slot_address()));
+ arguments->ShortPrint();
+ PrintF("\n");
}
- object->ShortPrint();
- PrintF("\n");
}
}
-
- ASSERT(materialization_object_index_ == materialized_objects_->length());
- ASSERT(materialization_value_index_ == materialized_values_->length());
}
}
@@ -1874,10 +1786,10 @@ static const char* TraceValueType(bool is_smi, bool is_native = false) {
void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
- int object_index,
+ int object_opcode,
int field_index) {
disasm::NameConverter converter;
- Address object_slot = deferred_objects_[object_index].slot_address();
+ Address object_slot = deferred_objects_.last().slot_address();
Translation::Opcode opcode =
static_cast<Translation::Opcode>(iterator->Next());
@@ -1890,6 +1802,7 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
case Translation::GETTER_STUB_FRAME:
case Translation::SETTER_STUB_FRAME:
case Translation::COMPILED_STUB_FRAME:
+ case Translation::ARGUMENTS_OBJECT:
UNREACHABLE();
return;
@@ -2059,50 +1972,6 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
AddObjectTaggedValue(value);
return;
}
-
- case Translation::DUPLICATED_OBJECT: {
- int object_index = iterator->Next();
- if (trace_) {
- PrintF(" nested @0x%08" V8PRIxPTR ": [field #%d] <- ",
- reinterpret_cast<intptr_t>(object_slot),
- field_index);
- isolate_->heap()->arguments_marker()->ShortPrint();
- PrintF(" ; duplicate of object #%d\n", object_index);
- }
- // Use the materialization marker value as a sentinel and fill in
- // the object after the deoptimized frame is built.
- intptr_t value = reinterpret_cast<intptr_t>(
- isolate_->heap()->arguments_marker());
- AddObjectDuplication(0, object_index);
- AddObjectTaggedValue(value);
- return;
- }
-
- case Translation::ARGUMENTS_OBJECT:
- case Translation::CAPTURED_OBJECT: {
- int length = iterator->Next();
- bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
- if (trace_) {
- PrintF(" nested @0x%08" V8PRIxPTR ": [field #%d] <- ",
- reinterpret_cast<intptr_t>(object_slot),
- field_index);
- isolate_->heap()->arguments_marker()->ShortPrint();
- PrintF(" ; object (length = %d, is_args = %d)\n", length, is_args);
- }
- // Use the materialization marker value as a sentinel and fill in
- // the object after the deoptimized frame is built.
- intptr_t value = reinterpret_cast<intptr_t>(
- isolate_->heap()->arguments_marker());
- AddObjectStart(0, length, is_args);
- AddObjectTaggedValue(value);
- // We save the object values on the side and materialize the actual
- // object after the deoptimized frame is built.
- int object_index = deferred_objects_.length() - 1;
- for (int i = 0; i < length; i++) {
- DoTranslateObject(iterator, object_index, i);
- }
- return;
- }
}
}
@@ -2342,48 +2211,25 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
return;
}
- case Translation::DUPLICATED_OBJECT: {
- int object_index = iterator->Next();
- if (trace_) {
- PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
- output_[frame_index]->GetTop() + output_offset,
- output_offset);
- isolate_->heap()->arguments_marker()->ShortPrint();
- PrintF(" ; duplicate of object #%d\n", object_index);
- }
- // Use the materialization marker value as a sentinel and fill in
- // the object after the deoptimized frame is built.
- intptr_t value = reinterpret_cast<intptr_t>(
- isolate_->heap()->arguments_marker());
- AddObjectDuplication(output_[frame_index]->GetTop() + output_offset,
- object_index);
- output_[frame_index]->SetFrameSlot(output_offset, value);
- return;
- }
-
- case Translation::ARGUMENTS_OBJECT:
- case Translation::CAPTURED_OBJECT: {
+ case Translation::ARGUMENTS_OBJECT: {
int length = iterator->Next();
- bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
output_[frame_index]->GetTop() + output_offset,
output_offset);
isolate_->heap()->arguments_marker()->ShortPrint();
- PrintF(" ; object (length = %d, is_args = %d)\n", length, is_args);
+ PrintF(" ; arguments object (length = %d)\n", length);
}
- // Use the materialization marker value as a sentinel and fill in
- // the object after the deoptimized frame is built.
+ // Use the arguments marker value as a sentinel and fill in the arguments
+ // object after the deoptimized frame is built.
intptr_t value = reinterpret_cast<intptr_t>(
isolate_->heap()->arguments_marker());
- AddObjectStart(output_[frame_index]->GetTop() + output_offset,
- length, is_args);
+ AddObjectStart(output_[frame_index]->GetTop() + output_offset, length);
output_[frame_index]->SetFrameSlot(output_offset, value);
- // We save the object values on the side and materialize the actual
- // object after the deoptimized frame is built.
- int object_index = deferred_objects_.length() - 1;
+ // We save the argument values on the side and materialize the actual
+ // arguments object after the deoptimized frame is built.
for (int i = 0; i < length; i++) {
- DoTranslateObject(iterator, object_index, i);
+ DoTranslateObject(iterator, Translation::ARGUMENTS_OBJECT, i);
}
return;
}
@@ -2560,9 +2406,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
break;
}
- case Translation::DUPLICATED_OBJECT:
- case Translation::ARGUMENTS_OBJECT:
- case Translation::CAPTURED_OBJECT: {
+ case Translation::ARGUMENTS_OBJECT: {
// Optimized code assumes that the argument object has not been
// materialized and so bypasses it when doing arguments access.
// We should have bailed out before starting the frame
@@ -2582,19 +2426,25 @@ void Deoptimizer::PatchInterruptCode(Code* unoptimized_code,
Code* replacement_code) {
// Iterate over the back edge table and patch every interrupt
// call to an unconditional call to the replacement code.
+ ASSERT(unoptimized_code->kind() == Code::FUNCTION);
int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level();
-
- for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
- !back_edges.Done();
- back_edges.Next()) {
- if (static_cast<int>(back_edges.loop_depth()) == loop_nesting_level) {
+ Address back_edge_cursor = unoptimized_code->instruction_start() +
+ unoptimized_code->back_edge_table_offset();
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor);
+ back_edge_cursor += kIntSize;
+ for (uint32_t i = 0; i < table_length; ++i) {
+ uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + 2 * kIntSize);
+ if (static_cast<int>(loop_depth) == loop_nesting_level) {
+ // Loop back edge has the loop depth that we want to patch.
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize);
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset;
PatchInterruptCodeAt(unoptimized_code,
- back_edges.pc(),
+ pc_after,
interrupt_code,
replacement_code);
}
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
}
-
unoptimized_code->set_back_edges_patched_for_osr(true);
#ifdef DEBUG
Deoptimizer::VerifyInterruptCode(
@@ -2607,20 +2457,25 @@ void Deoptimizer::RevertInterruptCode(Code* unoptimized_code,
Code* interrupt_code,
Code* replacement_code) {
// Iterate over the back edge table and revert the patched interrupt calls.
+ ASSERT(unoptimized_code->kind() == Code::FUNCTION);
ASSERT(unoptimized_code->back_edges_patched_for_osr());
int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level();
-
- for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
- !back_edges.Done();
- back_edges.Next()) {
- if (static_cast<int>(back_edges.loop_depth()) <= loop_nesting_level) {
+ Address back_edge_cursor = unoptimized_code->instruction_start() +
+ unoptimized_code->back_edge_table_offset();
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor);
+ back_edge_cursor += kIntSize;
+ for (uint32_t i = 0; i < table_length; ++i) {
+ uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + 2 * kIntSize);
+ if (static_cast<int>(loop_depth) <= loop_nesting_level) {
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize);
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset;
RevertInterruptCodeAt(unoptimized_code,
- back_edges.pc(),
+ pc_after,
interrupt_code,
replacement_code);
}
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
}
-
unoptimized_code->set_back_edges_patched_for_osr(false);
unoptimized_code->set_allow_osr_at_loop_nesting_level(0);
#ifdef DEBUG
@@ -2636,18 +2491,24 @@ void Deoptimizer::VerifyInterruptCode(Code* unoptimized_code,
Code* interrupt_code,
Code* replacement_code,
int loop_nesting_level) {
- for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
- !back_edges.Done();
- back_edges.Next()) {
- uint32_t loop_depth = back_edges.loop_depth();
+ CHECK(unoptimized_code->kind() == Code::FUNCTION);
+ Address back_edge_cursor = unoptimized_code->instruction_start() +
+ unoptimized_code->back_edge_table_offset();
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor);
+ back_edge_cursor += kIntSize;
+ for (uint32_t i = 0; i < table_length; ++i) {
+ uint32_t loop_depth = Memory::uint32_at(back_edge_cursor + 2 * kIntSize);
CHECK_LE(static_cast<int>(loop_depth), Code::kMaxLoopNestingMarker);
// Assert that all back edges for shallower loops (and only those)
// have already been patched.
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize);
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset;
CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
InterruptCodeIsPatched(unoptimized_code,
- back_edges.pc(),
+ pc_after,
interrupt_code,
replacement_code));
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
}
}
#endif // DEBUG
@@ -2710,16 +2571,9 @@ Object* Deoptimizer::ComputeLiteral(int index) const {
}
-void Deoptimizer::AddObjectStart(intptr_t slot, int length, bool is_args) {
+void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) {
ObjectMaterializationDescriptor object_desc(
- reinterpret_cast<Address>(slot), jsframe_count_, length, -1, is_args);
- deferred_objects_.Add(object_desc);
-}
-
-
-void Deoptimizer::AddObjectDuplication(intptr_t slot, int object_index) {
- ObjectMaterializationDescriptor object_desc(
- reinterpret_cast<Address>(slot), jsframe_count_, -1, object_index, false);
+ reinterpret_cast<Address>(slot_address), length);
deferred_objects_.Add(object_desc);
}
@@ -2947,18 +2801,6 @@ void Translation::BeginArgumentsObject(int args_length) {
}
-void Translation::BeginCapturedObject(int length) {
- buffer_->Add(CAPTURED_OBJECT, zone());
- buffer_->Add(length, zone());
-}
-
-
-void Translation::DuplicateObject(int object_index) {
- buffer_->Add(DUPLICATED_OBJECT, zone());
- buffer_->Add(object_index, zone());
-}
-
-
void Translation::StoreRegister(Register reg) {
buffer_->Add(REGISTER, zone());
buffer_->Add(reg.code(), zone());
@@ -3027,9 +2869,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
switch (opcode) {
case GETTER_STUB_FRAME:
case SETTER_STUB_FRAME:
- case DUPLICATED_OBJECT:
case ARGUMENTS_OBJECT:
- case CAPTURED_OBJECT:
case REGISTER:
case INT32_REGISTER:
case UINT32_REGISTER:
@@ -3089,12 +2929,8 @@ const char* Translation::StringFor(Opcode opcode) {
return "DOUBLE_STACK_SLOT";
case LITERAL:
return "LITERAL";
- case DUPLICATED_OBJECT:
- return "DUPLICATED_OBJECT";
case ARGUMENTS_OBJECT:
return "ARGUMENTS_OBJECT";
- case CAPTURED_OBJECT:
- return "CAPTURED_OBJECT";
}
UNREACHABLE();
return "";
@@ -3138,9 +2974,7 @@ SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator,
// Peeled off before getting here.
break;
- case Translation::DUPLICATED_OBJECT:
case Translation::ARGUMENTS_OBJECT:
- case Translation::CAPTURED_OBJECT:
// This can be only emitted for local slots not for argument slots.
break;
diff --git a/chromium/v8/src/deoptimizer.h b/chromium/v8/src/deoptimizer.h
index b6e4667a20d..7ad1ab0b2e7 100644
--- a/chromium/v8/src/deoptimizer.h
+++ b/chromium/v8/src/deoptimizer.h
@@ -77,31 +77,15 @@ class HeapNumberMaterializationDescriptor BASE_EMBEDDED {
class ObjectMaterializationDescriptor BASE_EMBEDDED {
public:
- ObjectMaterializationDescriptor(
- Address slot_address, int frame, int length, int duplicate, bool is_args)
- : slot_address_(slot_address),
- jsframe_index_(frame),
- object_length_(length),
- duplicate_object_(duplicate),
- is_arguments_(is_args) { }
+ ObjectMaterializationDescriptor(Address slot_address, int length)
+ : slot_address_(slot_address), object_length_(length) { }
Address slot_address() const { return slot_address_; }
- int jsframe_index() const { return jsframe_index_; }
int object_length() const { return object_length_; }
- int duplicate_object() const { return duplicate_object_; }
- bool is_arguments() const { return is_arguments_; }
-
- // Only used for allocated receivers in DoComputeConstructStubFrame.
- void patch_slot_address(intptr_t slot) {
- slot_address_ = reinterpret_cast<Address>(slot);
- }
private:
Address slot_address_;
- int jsframe_index_;
int object_length_;
- int duplicate_object_;
- bool is_arguments_;
};
@@ -388,7 +372,7 @@ class Deoptimizer : public Malloced {
int frame_index);
void DoTranslateObject(TranslationIterator* iterator,
- int object_index,
+ int object_opcode,
int field_index);
enum DeoptimizerTranslatedValueType {
@@ -416,28 +400,11 @@ class Deoptimizer : public Malloced {
Object* ComputeLiteral(int index) const;
- void AddObjectStart(intptr_t slot_address, int argc, bool is_arguments);
- void AddObjectDuplication(intptr_t slot, int object_index);
+ void AddObjectStart(intptr_t slot_address, int argc);
void AddObjectTaggedValue(intptr_t value);
void AddObjectDoubleValue(double value);
void AddDoubleValue(intptr_t slot_address, double value);
- bool ArgumentsObjectIsAdapted(int object_index) {
- ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
- int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
- return jsframe_has_adapted_arguments_[reverse_jsframe_index];
- }
-
- Handle<JSFunction> ArgumentsObjectFunction(int object_index) {
- ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
- int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
- return jsframe_functions_[reverse_jsframe_index];
- }
-
- // Helper function for heap object materialization.
- Handle<Object> MaterializeNextHeapObject();
- Handle<Object> MaterializeNextValue();
-
static void GenerateDeoptimizationEntries(
MacroAssembler* masm, int count, BailoutType type);
@@ -488,22 +455,10 @@ class Deoptimizer : public Malloced {
// Array of output frame descriptions.
FrameDescription** output_;
- // Deferred values to be materialized.
List<Object*> deferred_objects_tagged_values_;
List<double> deferred_objects_double_values_;
List<ObjectMaterializationDescriptor> deferred_objects_;
List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
-
- // Output frame information. Only used during heap object materialization.
- List<Handle<JSFunction> > jsframe_functions_;
- List<bool> jsframe_has_adapted_arguments_;
-
- // Materialized objects. Only used during heap object materialization.
- List<Handle<Object> >* materialized_values_;
- List<Handle<Object> >* materialized_objects_;
- int materialization_value_index_;
- int materialization_object_index_;
-
#ifdef DEBUG
DisallowHeapAllocation* disallow_heap_allocation_;
#endif // DEBUG
@@ -757,9 +712,7 @@ class Translation BASE_EMBEDDED {
SETTER_STUB_FRAME,
ARGUMENTS_ADAPTOR_FRAME,
COMPILED_STUB_FRAME,
- DUPLICATED_OBJECT,
ARGUMENTS_OBJECT,
- CAPTURED_OBJECT,
REGISTER,
INT32_REGISTER,
UINT32_REGISTER,
@@ -791,8 +744,6 @@ class Translation BASE_EMBEDDED {
void BeginGetterStubFrame(int literal_id);
void BeginSetterStubFrame(int literal_id);
void BeginArgumentsObject(int args_length);
- void BeginCapturedObject(int length);
- void DuplicateObject(int object_index);
void StoreRegister(Register reg);
void StoreInt32Register(Register reg);
void StoreUint32Register(Register reg);
diff --git a/chromium/v8/src/effects.h b/chromium/v8/src/effects.h
deleted file mode 100644
index 8e823634710..00000000000
--- a/chromium/v8/src/effects.h
+++ /dev/null
@@ -1,361 +0,0 @@
-// 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.
-
-#ifndef V8_EFFECTS_H_
-#define V8_EFFECTS_H_
-
-#include "v8.h"
-
-#include "types.h"
-
-namespace v8 {
-namespace internal {
-
-
-// A simple struct to represent (write) effects. A write is represented as a
-// modification of type bounds (e.g. of a variable).
-//
-// An effect can either be definite, if the write is known to have taken place,
-// or 'possible', if it was optional. The difference is relevant when composing
-// effects.
-//
-// There are two ways to compose effects: sequentially (they happen one after
-// the other) or alternatively (either one or the other happens). A definite
-// effect cancels out any previous effect upon sequencing. A possible effect
-// merges into a previous effect, i.e., type bounds are merged. Alternative
-// composition always merges bounds. It yields a possible effect if at least
-// one was only possible.
-struct Effect {
- enum Modality { POSSIBLE, DEFINITE };
-
- Modality modality;
- Bounds bounds;
-
- Effect() {}
- Effect(Bounds b, Modality m = DEFINITE) : modality(m), bounds(b) {}
-
- // The unknown effect.
- static Effect Unknown(Isolate* isolate) {
- return Effect(Bounds::Unbounded(isolate), POSSIBLE);
- }
-
- static Effect Forget(Isolate* isolate) {
- return Effect(Bounds::Unbounded(isolate), DEFINITE);
- }
-
- // Sequential composition, as in 'e1; e2'.
- static Effect Seq(Effect e1, Effect e2, Isolate* isolate) {
- if (e2.modality == DEFINITE) return e2;
- return Effect(Bounds::Either(e1.bounds, e2.bounds, isolate), e1.modality);
- }
-
- // Alternative composition, as in 'cond ? e1 : e2'.
- static Effect Alt(Effect e1, Effect e2, Isolate* isolate) {
- return Effect(
- Bounds::Either(e1.bounds, e2.bounds, isolate),
- e1.modality == POSSIBLE ? POSSIBLE : e2.modality);
- }
-};
-
-
-// Classes encapsulating sets of effects on variables.
-//
-// Effects maps variables to effects and supports sequential and alternative
-// composition.
-//
-// NestedEffects is an incremental representation that supports persistence
-// through functional extension. It represents the map as an adjoin of a list
-// of maps, whose tail can be shared.
-//
-// Both classes provide similar interfaces, implemented in parts through the
-// EffectsMixin below (using sandwich style, to work around the style guide's
-// MI restriction).
-//
-// We also (ab)use Effects/NestedEffects as a representation for abstract
-// store typings. In that case, only definite effects are of interest.
-
-template<class Var, class Base, class Effects>
-class EffectsMixin: public Base {
- public:
- explicit EffectsMixin(Zone* zone) : Base(zone) {}
-
- Effect Lookup(Var var) {
- Locator locator;
- return this->Find(var, &locator)
- ? locator.value() : Effect::Unknown(Base::isolate());
- }
-
- Bounds LookupBounds(Var var) {
- Effect effect = Lookup(var);
- return effect.modality == Effect::DEFINITE
- ? effect.bounds : Bounds::Unbounded(Base::isolate());
- }
-
- // Sequential composition.
- void Seq(Var var, Effect effect) {
- Locator locator;
- if (!this->Insert(var, &locator)) {
- effect = Effect::Seq(locator.value(), effect, Base::isolate());
- }
- locator.set_value(effect);
- }
-
- void Seq(Effects that) {
- SeqMerger<EffectsMixin> merge = { *this };
- that.ForEach(&merge);
- }
-
- // Alternative composition.
- void Alt(Var var, Effect effect) {
- Locator locator;
- if (!this->Insert(var, &locator)) {
- effect = Effect::Alt(locator.value(), effect, Base::isolate());
- }
- locator.set_value(effect);
- }
-
- void Alt(Effects that) {
- AltWeakener<EffectsMixin> weaken = { *this, that };
- this->ForEach(&weaken);
- AltMerger<EffectsMixin> merge = { *this };
- that.ForEach(&merge);
- }
-
- // Invalidation.
- void Forget() {
- Overrider override = {
- Effect::Forget(Base::isolate()), Effects(Base::zone()) };
- this->ForEach(&override);
- Seq(override.effects);
- }
-
- protected:
- typedef typename Base::Locator Locator;
-
- template<class Self>
- struct SeqMerger {
- void Call(Var var, Effect effect) { self.Seq(var, effect); }
- Self self;
- };
-
- template<class Self>
- struct AltMerger {
- void Call(Var var, Effect effect) { self.Alt(var, effect); }
- Self self;
- };
-
- template<class Self>
- struct AltWeakener {
- void Call(Var var, Effect effect) {
- if (effect.modality == Effect::DEFINITE && !other.Contains(var)) {
- effect.modality = Effect::POSSIBLE;
- Locator locator;
- self.Insert(var, &locator);
- locator.set_value(effect);
- }
- }
- Self self;
- Effects other;
- };
-
- struct Overrider {
- void Call(Var var, Effect effect) { effects.Seq(var, new_effect); }
- Effect new_effect;
- Effects effects;
- };
-};
-
-
-template<class Var, Var kNoVar> class Effects;
-template<class Var, Var kNoVar> class NestedEffectsBase;
-
-template<class Var, Var kNoVar>
-class EffectsBase {
- public:
- explicit EffectsBase(Zone* zone) : map_(new(zone) Mapping(zone)) {}
-
- bool IsEmpty() { return map_->is_empty(); }
-
- protected:
- friend class NestedEffectsBase<Var, kNoVar>;
- friend class
- EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >;
-
- Zone* zone() { return map_->allocator().zone(); }
- Isolate* isolate() { return zone()->isolate(); }
-
- struct SplayTreeConfig {
- typedef Var Key;
- typedef Effect Value;
- static const Var kNoKey = kNoVar;
- static Effect NoValue() { return Effect(); }
- static int Compare(int x, int y) { return y - x; }
- };
- typedef ZoneSplayTree<SplayTreeConfig> Mapping;
- typedef typename Mapping::Locator Locator;
-
- bool Contains(Var var) {
- ASSERT(var != kNoVar);
- return map_->Contains(var);
- }
- bool Find(Var var, Locator* locator) {
- ASSERT(var != kNoVar);
- return map_->Find(var, locator);
- }
- bool Insert(Var var, Locator* locator) {
- ASSERT(var != kNoVar);
- return map_->Insert(var, locator);
- }
-
- template<class Callback>
- void ForEach(Callback* callback) {
- return map_->ForEach(callback);
- }
-
- private:
- Mapping* map_;
-};
-
-template<class Var, Var kNoVar>
-const Var EffectsBase<Var, kNoVar>::SplayTreeConfig::kNoKey;
-
-template<class Var, Var kNoVar>
-class Effects: public
- EffectsMixin<Var, EffectsBase<Var, kNoVar>, Effects<Var, kNoVar> > {
- public:
- explicit Effects(Zone* zone)
- : EffectsMixin<Var, EffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >(zone)
- {}
-};
-
-
-template<class Var, Var kNoVar>
-class NestedEffectsBase {
- public:
- explicit NestedEffectsBase(Zone* zone) : node_(new(zone) Node(zone)) {}
-
- template<class Callback>
- void ForEach(Callback* callback) {
- if (node_->previous) NestedEffectsBase(node_->previous).ForEach(callback);
- node_->effects.ForEach(callback);
- }
-
- Effects<Var, kNoVar> Top() { return node_->effects; }
-
- bool IsEmpty() {
- for (Node* node = node_; node != NULL; node = node->previous) {
- if (!node->effects.IsEmpty()) return false;
- }
- return true;
- }
-
- protected:
- typedef typename EffectsBase<Var, kNoVar>::Locator Locator;
-
- Zone* zone() { return node_->zone; }
- Isolate* isolate() { return zone()->isolate(); }
-
- void push() { node_ = new(node_->zone) Node(node_->zone, node_); }
- void pop() { node_ = node_->previous; }
- bool is_empty() { return node_ == NULL; }
-
- bool Contains(Var var) {
- ASSERT(var != kNoVar);
- for (Node* node = node_; node != NULL; node = node->previous) {
- if (node->effects.Contains(var)) return true;
- }
- return false;
- }
-
- bool Find(Var var, Locator* locator) {
- ASSERT(var != kNoVar);
- for (Node* node = node_; node != NULL; node = node->previous) {
- if (node->effects.Find(var, locator)) return true;
- }
- return false;
- }
-
- bool Insert(Var var, Locator* locator);
-
- private:
- struct Node: ZoneObject {
- Zone* zone;
- Effects<Var, kNoVar> effects;
- Node* previous;
- explicit Node(Zone* zone, Node* previous = NULL)
- : zone(zone), effects(zone), previous(previous) {}
- };
-
- explicit NestedEffectsBase(Node* node) : node_(node) {}
-
- Node* node_;
-};
-
-
-template<class Var, Var kNoVar>
-bool NestedEffectsBase<Var, kNoVar>::Insert(Var var, Locator* locator) {
- ASSERT(var != kNoVar);
- if (!node_->effects.Insert(var, locator)) return false;
- Locator shadowed;
- for (Node* node = node_->previous; node != NULL; node = node->previous) {
- if (node->effects.Find(var, &shadowed)) {
- // Initialize with shadowed entry.
- locator->set_value(shadowed.value());
- return false;
- }
- }
- return true;
-}
-
-
-template<class Var, Var kNoVar>
-class NestedEffects: public
- EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> > {
- public:
- explicit NestedEffects(Zone* zone) :
- EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >(
- zone) {}
-
- // Create an extension of the current effect set. The current set should not
- // be modified while the extension is in use.
- NestedEffects Push() {
- NestedEffects result = *this;
- result.push();
- return result;
- }
-
- NestedEffects Pop() {
- NestedEffects result = *this;
- result.pop();
- ASSERT(!this->is_empty());
- return result;
- }
-};
-
-} } // namespace v8::internal
-
-#endif // V8_EFFECTS_H_
diff --git a/chromium/v8/src/execution.cc b/chromium/v8/src/execution.cc
index ecfa1db1ed8..d7b9cf5d596 100644
--- a/chromium/v8/src/execution.cc
+++ b/chromium/v8/src/execution.cc
@@ -206,12 +206,10 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func,
catcher.SetCaptureMessage(false);
*caught_exception = false;
- // Get isolate now, because handle might be persistent
- // and get destroyed in the next call.
- Isolate* isolate = func->GetIsolate();
Handle<Object> result = Invoke(false, func, receiver, argc, args,
caught_exception);
+ Isolate* isolate = func->GetIsolate();
if (*caught_exception) {
ASSERT(catcher.HasCaught());
ASSERT(isolate->has_pending_exception());
diff --git a/chromium/v8/src/extensions/i18n/collator.cc b/chromium/v8/src/extensions/i18n/collator.cc
new file mode 100644
index 00000000000..61b1d63e5c2
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/collator.cc
@@ -0,0 +1,366 @@
+// 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.
+// limitations under the License.
+
+#include "collator.h"
+
+#include "i18n-utils.h"
+#include "unicode/coll.h"
+#include "unicode/locid.h"
+#include "unicode/ucol.h"
+
+namespace v8_i18n {
+
+static icu::Collator* InitializeCollator(
+ v8::Handle<v8::String>, v8::Handle<v8::Object>, v8::Handle<v8::Object>);
+
+static icu::Collator* CreateICUCollator(
+ const icu::Locale&, v8::Handle<v8::Object>);
+
+static bool SetBooleanAttribute(
+ UColAttribute, const char*, v8::Handle<v8::Object>, icu::Collator*);
+
+static void SetResolvedSettings(
+ const icu::Locale&, icu::Collator*, v8::Handle<v8::Object>);
+
+static void SetBooleanSetting(
+ UColAttribute, icu::Collator*, const char*, v8::Handle<v8::Object>);
+
+icu::Collator* Collator::UnpackCollator(v8::Handle<v8::Object> obj) {
+ v8::HandleScope handle_scope;
+
+ if (obj->HasOwnProperty(v8::String::New("collator"))) {
+ return static_cast<icu::Collator*>(
+ obj->GetAlignedPointerFromInternalField(0));
+ }
+
+ return NULL;
+}
+
+void Collator::DeleteCollator(v8::Isolate* isolate,
+ v8::Persistent<v8::Object>* object,
+ void* param) {
+ // First delete the hidden C++ object.
+ // Unpacking should never return NULL here. That would only happen if
+ // this method is used as the weak callback for persistent handles not
+ // pointing to a collator.
+ v8::HandleScope handle_scope(isolate);
+ v8::Local<v8::Object> handle = v8::Local<v8::Object>::New(isolate, *object);
+ delete UnpackCollator(handle);
+
+ // Then dispose of the persistent handle to JS object.
+ object->Dispose(isolate);
+}
+
+
+// Throws a JavaScript exception.
+static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
+ // Returns undefined, and schedules an exception to be thrown.
+ return v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Collator method called on an object "
+ "that is not a Collator.")));
+}
+
+
+// When there's an ICU error, throw a JavaScript error with |message|.
+static v8::Handle<v8::Value> ThrowExceptionForICUError(const char* message) {
+ return v8::ThrowException(v8::Exception::Error(v8::String::New(message)));
+}
+
+
+// static
+void Collator::JSInternalCompare(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 3 || !args[0]->IsObject() ||
+ !args[1]->IsString() || !args[2]->IsString()) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Collator and two string arguments are required.")));
+ return;
+ }
+
+ icu::Collator* collator = UnpackCollator(args[0]->ToObject());
+ if (!collator) {
+ ThrowUnexpectedObjectError();
+ return;
+ }
+
+ v8::String::Value string_value1(args[1]);
+ v8::String::Value string_value2(args[2]);
+ const UChar* string1 = reinterpret_cast<const UChar*>(*string_value1);
+ const UChar* string2 = reinterpret_cast<const UChar*>(*string_value2);
+ UErrorCode status = U_ZERO_ERROR;
+ UCollationResult result = collator->compare(
+ string1, string_value1.length(), string2, string_value2.length(), status);
+
+ if (U_FAILURE(status)) {
+ ThrowExceptionForICUError(
+ "Internal error. Unexpected failure in Collator.compare.");
+ return;
+ }
+
+ args.GetReturnValue().Set(result);
+}
+
+void Collator::JSCreateCollator(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsObject() ||
+ !args[2]->IsObject()) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Internal error, wrong parameters.")));
+ return;
+ }
+
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::ObjectTemplate> intl_collator_template =
+ Utils::GetTemplate(isolate);
+
+ // Create an empty object wrapper.
+ v8::Local<v8::Object> local_object = intl_collator_template->NewInstance();
+ // But the handle shouldn't be empty.
+ // That can happen if there was a stack overflow when creating the object.
+ if (local_object.IsEmpty()) {
+ args.GetReturnValue().Set(local_object);
+ return;
+ }
+
+ // Set collator as internal field of the resulting JS object.
+ icu::Collator* collator = InitializeCollator(
+ args[0]->ToString(), args[1]->ToObject(), args[2]->ToObject());
+
+ if (!collator) {
+ v8::ThrowException(v8::Exception::Error(v8::String::New(
+ "Internal error. Couldn't create ICU collator.")));
+ return;
+ } else {
+ local_object->SetAlignedPointerInInternalField(0, collator);
+
+ // Make it safer to unpack later on.
+ v8::TryCatch try_catch;
+ local_object->Set(v8::String::New("collator"), v8::String::New("valid"));
+ if (try_catch.HasCaught()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Internal error, couldn't set property.")));
+ return;
+ }
+ }
+
+ v8::Persistent<v8::Object> wrapper(isolate, local_object);
+ // Make object handle weak so we can delete iterator once GC kicks in.
+ wrapper.MakeWeak<void>(NULL, &DeleteCollator);
+ args.GetReturnValue().Set(wrapper);
+ wrapper.ClearAndLeak();
+}
+
+static icu::Collator* InitializeCollator(v8::Handle<v8::String> locale,
+ v8::Handle<v8::Object> options,
+ v8::Handle<v8::Object> resolved) {
+ // Convert BCP47 into ICU locale format.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale icu_locale;
+ char icu_result[ULOC_FULLNAME_CAPACITY];
+ int icu_length = 0;
+ v8::String::AsciiValue bcp47_locale(locale);
+ if (bcp47_locale.length() != 0) {
+ uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
+ &icu_length, &status);
+ if (U_FAILURE(status) || icu_length == 0) {
+ return NULL;
+ }
+ icu_locale = icu::Locale(icu_result);
+ }
+
+ icu::Collator* collator = CreateICUCollator(icu_locale, options);
+ if (!collator) {
+ // Remove extensions and try again.
+ icu::Locale no_extension_locale(icu_locale.getBaseName());
+ collator = CreateICUCollator(no_extension_locale, options);
+
+ // Set resolved settings (pattern, numbering system).
+ SetResolvedSettings(no_extension_locale, collator, resolved);
+ } else {
+ SetResolvedSettings(icu_locale, collator, resolved);
+ }
+
+ return collator;
+}
+
+static icu::Collator* CreateICUCollator(
+ const icu::Locale& icu_locale, v8::Handle<v8::Object> options) {
+ // Make collator from options.
+ icu::Collator* collator = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ collator = icu::Collator::createInstance(icu_locale, status);
+
+ if (U_FAILURE(status)) {
+ delete collator;
+ return NULL;
+ }
+
+ // Set flags first, and then override them with sensitivity if necessary.
+ SetBooleanAttribute(UCOL_NUMERIC_COLLATION, "numeric", options, collator);
+
+ // Normalization is always on, by the spec. We are free to optimize
+ // if the strings are already normalized (but we don't have a way to tell
+ // that right now).
+ collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
+
+ icu::UnicodeString case_first;
+ if (Utils::ExtractStringSetting(options, "caseFirst", &case_first)) {
+ if (case_first == UNICODE_STRING_SIMPLE("upper")) {
+ collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
+ } else if (case_first == UNICODE_STRING_SIMPLE("lower")) {
+ collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
+ } else {
+ // Default (false/off).
+ collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
+ }
+ }
+
+ icu::UnicodeString sensitivity;
+ if (Utils::ExtractStringSetting(options, "sensitivity", &sensitivity)) {
+ if (sensitivity == UNICODE_STRING_SIMPLE("base")) {
+ collator->setStrength(icu::Collator::PRIMARY);
+ } else if (sensitivity == UNICODE_STRING_SIMPLE("accent")) {
+ collator->setStrength(icu::Collator::SECONDARY);
+ } else if (sensitivity == UNICODE_STRING_SIMPLE("case")) {
+ collator->setStrength(icu::Collator::PRIMARY);
+ collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status);
+ } else {
+ // variant (default)
+ collator->setStrength(icu::Collator::TERTIARY);
+ }
+ }
+
+ bool ignore;
+ if (Utils::ExtractBooleanSetting(options, "ignorePunctuation", &ignore)) {
+ if (ignore) {
+ collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
+ }
+ }
+
+ return collator;
+}
+
+static bool SetBooleanAttribute(UColAttribute attribute,
+ const char* name,
+ v8::Handle<v8::Object> options,
+ icu::Collator* collator) {
+ UErrorCode status = U_ZERO_ERROR;
+ bool result;
+ if (Utils::ExtractBooleanSetting(options, name, &result)) {
+ collator->setAttribute(attribute, result ? UCOL_ON : UCOL_OFF, status);
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void SetResolvedSettings(const icu::Locale& icu_locale,
+ icu::Collator* collator,
+ v8::Handle<v8::Object> resolved) {
+ SetBooleanSetting(UCOL_NUMERIC_COLLATION, collator, "numeric", resolved);
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ switch (collator->getAttribute(UCOL_CASE_FIRST, status)) {
+ case UCOL_LOWER_FIRST:
+ resolved->Set(v8::String::New("caseFirst"), v8::String::New("lower"));
+ break;
+ case UCOL_UPPER_FIRST:
+ resolved->Set(v8::String::New("caseFirst"), v8::String::New("upper"));
+ break;
+ default:
+ resolved->Set(v8::String::New("caseFirst"), v8::String::New("false"));
+ }
+
+ switch (collator->getAttribute(UCOL_STRENGTH, status)) {
+ case UCOL_PRIMARY: {
+ resolved->Set(v8::String::New("strength"), v8::String::New("primary"));
+
+ // case level: true + s1 -> case, s1 -> base.
+ if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
+ resolved->Set(v8::String::New("sensitivity"), v8::String::New("case"));
+ } else {
+ resolved->Set(v8::String::New("sensitivity"), v8::String::New("base"));
+ }
+ break;
+ }
+ case UCOL_SECONDARY:
+ resolved->Set(v8::String::New("strength"), v8::String::New("secondary"));
+ resolved->Set(v8::String::New("sensitivity"), v8::String::New("accent"));
+ break;
+ case UCOL_TERTIARY:
+ resolved->Set(v8::String::New("strength"), v8::String::New("tertiary"));
+ resolved->Set(v8::String::New("sensitivity"), v8::String::New("variant"));
+ break;
+ case UCOL_QUATERNARY:
+ // We shouldn't get quaternary and identical from ICU, but if we do
+ // put them into variant.
+ resolved->Set(v8::String::New("strength"), v8::String::New("quaternary"));
+ resolved->Set(v8::String::New("sensitivity"), v8::String::New("variant"));
+ break;
+ default:
+ resolved->Set(v8::String::New("strength"), v8::String::New("identical"));
+ resolved->Set(v8::String::New("sensitivity"), v8::String::New("variant"));
+ }
+
+ if (UCOL_SHIFTED == collator->getAttribute(UCOL_ALTERNATE_HANDLING, status)) {
+ resolved->Set(v8::String::New("ignorePunctuation"),
+ v8::Boolean::New(true));
+ } else {
+ resolved->Set(v8::String::New("ignorePunctuation"),
+ v8::Boolean::New(false));
+ }
+
+ // Set the locale
+ char result[ULOC_FULLNAME_CAPACITY];
+ status = U_ZERO_ERROR;
+ uloc_toLanguageTag(
+ icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
+ if (U_SUCCESS(status)) {
+ resolved->Set(v8::String::New("locale"), v8::String::New(result));
+ } else {
+ // This would never happen, since we got the locale from ICU.
+ resolved->Set(v8::String::New("locale"), v8::String::New("und"));
+ }
+}
+
+static void SetBooleanSetting(UColAttribute attribute,
+ icu::Collator* collator,
+ const char* property,
+ v8::Handle<v8::Object> resolved) {
+ UErrorCode status = U_ZERO_ERROR;
+ if (UCOL_ON == collator->getAttribute(attribute, status)) {
+ resolved->Set(v8::String::New(property), v8::Boolean::New(true));
+ } else {
+ resolved->Set(v8::String::New(property), v8::Boolean::New(false));
+ }
+}
+
+} // namespace v8_i18n
diff --git a/chromium/v8/src/extensions/i18n/collator.h b/chromium/v8/src/extensions/i18n/collator.h
new file mode 100644
index 00000000000..a3991b9ed24
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/collator.h
@@ -0,0 +1,68 @@
+// 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.
+// limitations under the License.
+
+#ifndef V8_EXTENSIONS_I18N_COLLATOR_H_
+#define V8_EXTENSIONS_I18N_COLLATOR_H_
+
+#include "unicode/uversion.h"
+#include "v8.h"
+
+namespace U_ICU_NAMESPACE {
+class Collator;
+class UnicodeString;
+}
+
+namespace v8_i18n {
+
+class Collator {
+ public:
+ static void JSCreateCollator(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ // Helper methods for various bindings.
+
+ // Unpacks collator object from corresponding JavaScript object.
+ static icu::Collator* UnpackCollator(v8::Handle<v8::Object> obj);
+
+ // Release memory we allocated for the Collator once the JS object that
+ // holds the pointer gets garbage collected.
+ static void DeleteCollator(v8::Isolate* isolate,
+ v8::Persistent<v8::Object>* object,
+ void* param);
+
+ // Compare two strings and returns -1, 0 and 1 depending on
+ // whether string1 is smaller than, equal to or larger than string2.
+ static void JSInternalCompare(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ private:
+ Collator() {}
+};
+
+} // namespace v8_i18n
+
+#endif // V8_EXTENSIONS_I18N_COLLATOR_H_
diff --git a/chromium/v8/src/extensions/i18n/collator.js b/chromium/v8/src/extensions/i18n/collator.js
index d8d247b36f4..3483515bef2 100644
--- a/chromium/v8/src/extensions/i18n/collator.js
+++ b/chromium/v8/src/extensions/i18n/collator.js
@@ -35,6 +35,8 @@
* Useful for subclassing.
*/
function initializeCollator(collator, locales, options) {
+ native function NativeJSCreateCollator();
+
if (collator.hasOwnProperty('__initializedIntlObject')) {
throw new TypeError('Trying to re-initialize Collator object.');
}
@@ -101,9 +103,9 @@ function initializeCollator(collator, locales, options) {
usage: {value: internalOptions.usage, writable: true}
});
- var internalCollator = %CreateCollator(requestedLocale,
- internalOptions,
- resolved);
+ var internalCollator = NativeJSCreateCollator(requestedLocale,
+ internalOptions,
+ resolved);
// Writable, configurable and enumerable are set to false by default.
Object.defineProperty(collator, 'collator', {value: internalCollator});
@@ -202,7 +204,8 @@ function initializeCollator(collator, locales, options) {
* the sort order, or x comes after y in the sort order, respectively.
*/
function compare(collator, x, y) {
- return %InternalCompare(collator.collator, String(x), String(y));
+ native function NativeJSInternalCompare();
+ return NativeJSInternalCompare(collator.collator, String(x), String(y));
};
diff --git a/chromium/v8/src/extensions/i18n/date-format.cc b/chromium/v8/src/extensions/i18n/date-format.cc
new file mode 100644
index 00000000000..1058e37a58c
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/date-format.cc
@@ -0,0 +1,329 @@
+// 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.
+// limitations under the License.
+
+#include "date-format.h"
+
+#include <string.h>
+
+#include "i18n-utils.h"
+#include "unicode/calendar.h"
+#include "unicode/dtfmtsym.h"
+#include "unicode/dtptngen.h"
+#include "unicode/locid.h"
+#include "unicode/numsys.h"
+#include "unicode/smpdtfmt.h"
+#include "unicode/timezone.h"
+
+namespace v8_i18n {
+
+static icu::SimpleDateFormat* InitializeDateTimeFormat(v8::Handle<v8::String>,
+ v8::Handle<v8::Object>,
+ v8::Handle<v8::Object>);
+static icu::SimpleDateFormat* CreateICUDateFormat(const icu::Locale&,
+ v8::Handle<v8::Object>);
+static void SetResolvedSettings(const icu::Locale&,
+ icu::SimpleDateFormat*,
+ v8::Handle<v8::Object>);
+
+icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
+ v8::Handle<v8::Object> obj) {
+ v8::HandleScope handle_scope;
+
+ if (obj->HasOwnProperty(v8::String::New("dateFormat"))) {
+ return static_cast<icu::SimpleDateFormat*>(
+ obj->GetAlignedPointerFromInternalField(0));
+ }
+
+ return NULL;
+}
+
+void DateFormat::DeleteDateFormat(v8::Isolate* isolate,
+ v8::Persistent<v8::Object>* object,
+ void* param) {
+ // First delete the hidden C++ object.
+ // Unpacking should never return NULL here. That would only happen if
+ // this method is used as the weak callback for persistent handles not
+ // pointing to a date time formatter.
+ v8::HandleScope handle_scope(isolate);
+ v8::Local<v8::Object> handle = v8::Local<v8::Object>::New(isolate, *object);
+ delete UnpackDateFormat(handle);
+
+ // Then dispose of the persistent handle to JS object.
+ object->Dispose(isolate);
+}
+
+void DateFormat::JSInternalFormat(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ double millis = 0.0;
+ if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsDate()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New(
+ "Internal error. Formatter and date value have to be specified.")));
+ return;
+ } else {
+ millis = v8::Date::Cast(*args[1])->NumberValue();
+ }
+
+ icu::SimpleDateFormat* date_format = UnpackDateFormat(args[0]->ToObject());
+ if (!date_format) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("DateTimeFormat method called on an object "
+ "that is not a DateTimeFormat.")));
+ return;
+ }
+
+ icu::UnicodeString result;
+ date_format->format(millis, result);
+
+ args.GetReturnValue().Set(v8::String::New(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length()));
+}
+
+void DateFormat::JSInternalParse(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ icu::UnicodeString string_date;
+ if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsString()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New(
+ "Internal error. Formatter and string have to be specified.")));
+ return;
+ } else {
+ if (!Utils::V8StringToUnicodeString(args[1], &string_date)) {
+ string_date = "";
+ }
+ }
+
+ icu::SimpleDateFormat* date_format = UnpackDateFormat(args[0]->ToObject());
+ if (!date_format) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("DateTimeFormat method called on an object "
+ "that is not a DateTimeFormat.")));
+ return;
+ }
+
+ UErrorCode status = U_ZERO_ERROR;
+ UDate date = date_format->parse(string_date, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ args.GetReturnValue().Set(v8::Date::New(static_cast<double>(date)));
+}
+
+void DateFormat::JSCreateDateTimeFormat(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 3 ||
+ !args[0]->IsString() ||
+ !args[1]->IsObject() ||
+ !args[2]->IsObject()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Internal error, wrong parameters.")));
+ return;
+ }
+
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::ObjectTemplate> date_format_template =
+ Utils::GetTemplate(isolate);
+
+ // Create an empty object wrapper.
+ v8::Local<v8::Object> local_object = date_format_template->NewInstance();
+ // But the handle shouldn't be empty.
+ // That can happen if there was a stack overflow when creating the object.
+ if (local_object.IsEmpty()) {
+ args.GetReturnValue().Set(local_object);
+ return;
+ }
+
+ // Set date time formatter as internal field of the resulting JS object.
+ icu::SimpleDateFormat* date_format = InitializeDateTimeFormat(
+ args[0]->ToString(), args[1]->ToObject(), args[2]->ToObject());
+
+ if (!date_format) {
+ v8::ThrowException(v8::Exception::Error(v8::String::New(
+ "Internal error. Couldn't create ICU date time formatter.")));
+ return;
+ } else {
+ local_object->SetAlignedPointerInInternalField(0, date_format);
+
+ v8::TryCatch try_catch;
+ local_object->Set(v8::String::New("dateFormat"), v8::String::New("valid"));
+ if (try_catch.HasCaught()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Internal error, couldn't set property.")));
+ return;
+ }
+ }
+
+ v8::Persistent<v8::Object> wrapper(isolate, local_object);
+ // Make object handle weak so we can delete iterator once GC kicks in.
+ wrapper.MakeWeak<void>(NULL, &DeleteDateFormat);
+ args.GetReturnValue().Set(wrapper);
+ wrapper.ClearAndLeak();
+}
+
+static icu::SimpleDateFormat* InitializeDateTimeFormat(
+ v8::Handle<v8::String> locale,
+ v8::Handle<v8::Object> options,
+ v8::Handle<v8::Object> resolved) {
+ // Convert BCP47 into ICU locale format.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale icu_locale;
+ char icu_result[ULOC_FULLNAME_CAPACITY];
+ int icu_length = 0;
+ v8::String::AsciiValue bcp47_locale(locale);
+ if (bcp47_locale.length() != 0) {
+ uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
+ &icu_length, &status);
+ if (U_FAILURE(status) || icu_length == 0) {
+ return NULL;
+ }
+ icu_locale = icu::Locale(icu_result);
+ }
+
+ icu::SimpleDateFormat* date_format = CreateICUDateFormat(icu_locale, options);
+ if (!date_format) {
+ // Remove extensions and try again.
+ icu::Locale no_extension_locale(icu_locale.getBaseName());
+ date_format = CreateICUDateFormat(no_extension_locale, options);
+
+ // Set resolved settings (pattern, numbering system, calendar).
+ SetResolvedSettings(no_extension_locale, date_format, resolved);
+ } else {
+ SetResolvedSettings(icu_locale, date_format, resolved);
+ }
+
+ return date_format;
+}
+
+static icu::SimpleDateFormat* CreateICUDateFormat(
+ const icu::Locale& icu_locale, v8::Handle<v8::Object> options) {
+ // Create time zone as specified by the user. We have to re-create time zone
+ // since calendar takes ownership.
+ icu::TimeZone* tz = NULL;
+ icu::UnicodeString timezone;
+ if (Utils::ExtractStringSetting(options, "timeZone", &timezone)) {
+ tz = icu::TimeZone::createTimeZone(timezone);
+ } else {
+ tz = icu::TimeZone::createDefault();
+ }
+
+ // Create a calendar using locale, and apply time zone to it.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Calendar* calendar =
+ icu::Calendar::createInstance(tz, icu_locale, status);
+
+ // Make formatter from skeleton. Calendar and numbering system are added
+ // to the locale as Unicode extension (if they were specified at all).
+ icu::SimpleDateFormat* date_format = NULL;
+ icu::UnicodeString skeleton;
+ if (Utils::ExtractStringSetting(options, "skeleton", &skeleton)) {
+ icu::DateTimePatternGenerator* generator =
+ icu::DateTimePatternGenerator::createInstance(icu_locale, status);
+ icu::UnicodeString pattern;
+ if (U_SUCCESS(status)) {
+ pattern = generator->getBestPattern(skeleton, status);
+ delete generator;
+ }
+
+ date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
+ if (U_SUCCESS(status)) {
+ date_format->adoptCalendar(calendar);
+ }
+ }
+
+ if (U_FAILURE(status)) {
+ delete calendar;
+ delete date_format;
+ date_format = NULL;
+ }
+
+ return date_format;
+}
+
+static void SetResolvedSettings(const icu::Locale& icu_locale,
+ icu::SimpleDateFormat* date_format,
+ v8::Handle<v8::Object> resolved) {
+ UErrorCode status = U_ZERO_ERROR;
+ icu::UnicodeString pattern;
+ date_format->toPattern(pattern);
+ resolved->Set(v8::String::New("pattern"),
+ v8::String::New(reinterpret_cast<const uint16_t*>(
+ pattern.getBuffer()), pattern.length()));
+
+ // Set time zone and calendar.
+ if (date_format) {
+ const icu::Calendar* calendar = date_format->getCalendar();
+ const char* calendar_name = calendar->getType();
+ resolved->Set(v8::String::New("calendar"), v8::String::New(calendar_name));
+
+ const icu::TimeZone& tz = calendar->getTimeZone();
+ icu::UnicodeString time_zone;
+ tz.getID(time_zone);
+
+ icu::UnicodeString canonical_time_zone;
+ icu::TimeZone::getCanonicalID(time_zone, canonical_time_zone, status);
+ if (U_SUCCESS(status)) {
+ if (canonical_time_zone == UNICODE_STRING_SIMPLE("Etc/GMT")) {
+ resolved->Set(v8::String::New("timeZone"), v8::String::New("UTC"));
+ } else {
+ resolved->Set(v8::String::New("timeZone"),
+ v8::String::New(reinterpret_cast<const uint16_t*>(
+ canonical_time_zone.getBuffer()),
+ canonical_time_zone.length()));
+ }
+ }
+ }
+
+ // Ugly hack. ICU doesn't expose numbering system in any way, so we have
+ // to assume that for given locale NumberingSystem constructor produces the
+ // same digits as NumberFormat/Calendar would.
+ status = U_ZERO_ERROR;
+ icu::NumberingSystem* numbering_system =
+ icu::NumberingSystem::createInstance(icu_locale, status);
+ if (U_SUCCESS(status)) {
+ const char* ns = numbering_system->getName();
+ resolved->Set(v8::String::New("numberingSystem"), v8::String::New(ns));
+ } else {
+ resolved->Set(v8::String::New("numberingSystem"), v8::Undefined());
+ }
+ delete numbering_system;
+
+ // Set the locale
+ char result[ULOC_FULLNAME_CAPACITY];
+ status = U_ZERO_ERROR;
+ uloc_toLanguageTag(
+ icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
+ if (U_SUCCESS(status)) {
+ resolved->Set(v8::String::New("locale"), v8::String::New(result));
+ } else {
+ // This would never happen, since we got the locale from ICU.
+ resolved->Set(v8::String::New("locale"), v8::String::New("und"));
+ }
+}
+
+} // namespace v8_i18n
diff --git a/chromium/v8/src/extensions/i18n/date-format.h b/chromium/v8/src/extensions/i18n/date-format.h
new file mode 100644
index 00000000000..daa5964e254
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/date-format.h
@@ -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.
+// limitations under the License.
+
+#ifndef V8_EXTENSIONS_I18N_DATE_FORMAT_H_
+#define V8_EXTENSIONS_I18N_DATE_FORMAT_H_
+
+#include "unicode/uversion.h"
+#include "v8.h"
+
+namespace U_ICU_NAMESPACE {
+class SimpleDateFormat;
+}
+
+namespace v8_i18n {
+
+class DateFormat {
+ public:
+ static void JSCreateDateTimeFormat(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ // Helper methods for various bindings.
+
+ // Unpacks date format object from corresponding JavaScript object.
+ static icu::SimpleDateFormat* UnpackDateFormat(
+ v8::Handle<v8::Object> obj);
+
+ // Release memory we allocated for the DateFormat once the JS object that
+ // holds the pointer gets garbage collected.
+ static void DeleteDateFormat(v8::Isolate* isolate,
+ v8::Persistent<v8::Object>* object,
+ void* param);
+
+ // Formats date and returns corresponding string.
+ static void JSInternalFormat(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ // Parses date and returns corresponding Date object or undefined if parse
+ // failed.
+ static void JSInternalParse(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ private:
+ DateFormat();
+};
+
+} // namespace v8_i18n
+
+#endif // V8_EXTENSIONS_I18N_DATE_FORMAT_H_
diff --git a/chromium/v8/src/extensions/i18n/date-format.js b/chromium/v8/src/extensions/i18n/date-format.js
index b1d28e535cd..04e7a7c7b9d 100644
--- a/chromium/v8/src/extensions/i18n/date-format.js
+++ b/chromium/v8/src/extensions/i18n/date-format.js
@@ -235,6 +235,7 @@ function toDateTimeOptions(options, required, defaults) {
* Useful for subclassing.
*/
function initializeDateTimeFormat(dateFormat, locales, options) {
+ native function NativeJSCreateDateTimeFormat();
if (dateFormat.hasOwnProperty('__initializedIntlObject')) {
throw new TypeError('Trying to re-initialize DateTimeFormat object.');
@@ -291,7 +292,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
year: {writable: true}
});
- var formatter = %CreateDateTimeFormat(
+ var formatter = NativeJSCreateDateTimeFormat(
requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved);
if (tz !== undefined && tz !== resolved.timeZone) {
@@ -408,6 +409,8 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
* DateTimeFormat.
*/
function formatDate(formatter, dateValue) {
+ native function NativeJSInternalDateFormat();
+
var dateMs;
if (dateValue === undefined) {
dateMs = Date.now();
@@ -419,7 +422,7 @@ function formatDate(formatter, dateValue) {
throw new RangeError('Provided date is not in valid range.');
}
- return %InternalDateFormat(formatter.formatter, new Date(dateMs));
+ return NativeJSInternalDateFormat(formatter.formatter, new Date(dateMs));
}
@@ -430,7 +433,8 @@ function formatDate(formatter, dateValue) {
* Returns undefined if date string cannot be parsed.
*/
function parseDate(formatter, value) {
- return %InternalDateParse(formatter.formatter, String(value));
+ native function NativeJSInternalDateParse();
+ return NativeJSInternalDateParse(formatter.formatter, String(value));
}
diff --git a/chromium/v8/src/extensions/i18n/i18n-extension.cc b/chromium/v8/src/extensions/i18n/i18n-extension.cc
index e2cba8eb9ef..1c77b8899fb 100644
--- a/chromium/v8/src/extensions/i18n/i18n-extension.cc
+++ b/chromium/v8/src/extensions/i18n/i18n-extension.cc
@@ -29,7 +29,11 @@
#include "i18n-extension.h"
#include "break-iterator.h"
+#include "collator.h"
+#include "date-format.h"
+#include "locale.h"
#include "natives.h"
+#include "number-format.h"
using v8::internal::I18NNatives;
@@ -45,6 +49,42 @@ Extension::Extension()
v8::Handle<v8::FunctionTemplate> Extension::GetNativeFunction(
v8::Handle<v8::String> name) {
+ // Standalone, helper methods.
+ if (name->Equals(v8::String::New("NativeJSCanonicalizeLanguageTag"))) {
+ return v8::FunctionTemplate::New(JSCanonicalizeLanguageTag);
+ } else if (name->Equals(v8::String::New("NativeJSAvailableLocalesOf"))) {
+ return v8::FunctionTemplate::New(JSAvailableLocalesOf);
+ } else if (name->Equals(v8::String::New("NativeJSGetDefaultICULocale"))) {
+ return v8::FunctionTemplate::New(JSGetDefaultICULocale);
+ } else if (name->Equals(v8::String::New("NativeJSGetLanguageTagVariants"))) {
+ return v8::FunctionTemplate::New(JSGetLanguageTagVariants);
+ }
+
+ // Date format and parse.
+ if (name->Equals(v8::String::New("NativeJSCreateDateTimeFormat"))) {
+ return v8::FunctionTemplate::New(DateFormat::JSCreateDateTimeFormat);
+ } else if (name->Equals(v8::String::New("NativeJSInternalDateFormat"))) {
+ return v8::FunctionTemplate::New(DateFormat::JSInternalFormat);
+ } else if (name->Equals(v8::String::New("NativeJSInternalDateParse"))) {
+ return v8::FunctionTemplate::New(DateFormat::JSInternalParse);
+ }
+
+ // Number format and parse.
+ if (name->Equals(v8::String::New("NativeJSCreateNumberFormat"))) {
+ return v8::FunctionTemplate::New(NumberFormat::JSCreateNumberFormat);
+ } else if (name->Equals(v8::String::New("NativeJSInternalNumberFormat"))) {
+ return v8::FunctionTemplate::New(NumberFormat::JSInternalFormat);
+ } else if (name->Equals(v8::String::New("NativeJSInternalNumberParse"))) {
+ return v8::FunctionTemplate::New(NumberFormat::JSInternalParse);
+ }
+
+ // Collator.
+ if (name->Equals(v8::String::New("NativeJSCreateCollator"))) {
+ return v8::FunctionTemplate::New(Collator::JSCreateCollator);
+ } else if (name->Equals(v8::String::New("NativeJSInternalCompare"))) {
+ return v8::FunctionTemplate::New(Collator::JSInternalCompare);
+ }
+
// Break iterator.
if (name->Equals(v8::String::New("NativeJSCreateBreakIterator"))) {
return v8::FunctionTemplate::New(BreakIterator::JSCreateBreakIterator);
diff --git a/chromium/v8/src/extensions/i18n/i18n-utils.cc b/chromium/v8/src/extensions/i18n/i18n-utils.cc
index 8c87f0715b9..eac11669047 100644
--- a/chromium/v8/src/extensions/i18n/i18n-utils.cc
+++ b/chromium/v8/src/extensions/i18n/i18n-utils.cc
@@ -141,37 +141,35 @@ void Utils::AsciiToUChar(const char* source,
}
-static v8::Local<v8::ObjectTemplate> ToLocal(i::Handle<i::Object> handle) {
- return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(handle));
-}
-
-
-template<int internal_fields, i::EternalHandles::SingletonHandle field>
-static v8::Local<v8::ObjectTemplate> GetEternal(v8::Isolate* external) {
- i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external);
- if (isolate->eternal_handles()->Exists(field)) {
- return ToLocal(isolate->eternal_handles()->GetSingleton(field));
- }
- v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
- raw_template->SetInternalFieldCount(internal_fields);
- return ToLocal(
- isolate->eternal_handles()->CreateSingleton(
- isolate,
- *v8::Utils::OpenHandle(*raw_template),
- field));
-}
-
-
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate(v8::Isolate* isolate) {
- return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
+ i::Isolate* internal = reinterpret_cast<i::Isolate*>(isolate);
+ if (internal->heap()->i18n_template_one() ==
+ internal->heap()->the_hole_value()) {
+ v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
+ raw_template->SetInternalFieldCount(1);
+ internal->heap()
+ ->SetI18nTemplateOne(*v8::Utils::OpenHandle(*raw_template));
+ }
+
+ return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(
+ internal->factory()->i18n_template_one()));
}
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate2(v8::Isolate* isolate) {
- return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
-}
+ i::Isolate* internal = reinterpret_cast<i::Isolate*>(isolate);
+ if (internal->heap()->i18n_template_two() ==
+ internal->heap()->the_hole_value()) {
+ v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
+ raw_template->SetInternalFieldCount(2);
+ internal->heap()
+ ->SetI18nTemplateTwo(*v8::Utils::OpenHandle(*raw_template));
+ }
+ return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(
+ internal->factory()->i18n_template_two()));
+}
} // namespace v8_i18n
diff --git a/chromium/v8/src/extensions/i18n/i18n-utils.js b/chromium/v8/src/extensions/i18n/i18n-utils.js
index 545082ecbba..d7e9486c507 100644
--- a/chromium/v8/src/extensions/i18n/i18n-utils.js
+++ b/chromium/v8/src/extensions/i18n/i18n-utils.js
@@ -255,6 +255,8 @@ function resolveLocale(service, requestedLocales, options) {
* lookup algorithm.
*/
function lookupMatcher(service, requestedLocales) {
+ native function NativeJSGetDefaultICULocale();
+
if (service.match(SERVICE_RE) === null) {
throw new Error('Internal error, wrong service type: ' + service);
}
@@ -285,7 +287,7 @@ function lookupMatcher(service, requestedLocales) {
// Didn't find a match, return default.
if (DEFAULT_ICU_LOCALE === undefined) {
- DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
+ DEFAULT_ICU_LOCALE = NativeJSGetDefaultICULocale();
}
return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
@@ -444,12 +446,14 @@ function getOptimalLanguageTag(original, resolved) {
// Returns Array<Object>, where each object has maximized and base properties.
// Maximized: zh -> zh-Hans-CN
// Base: zh-CN-u-ca-gregory -> zh-CN
+ native function NativeJSGetLanguageTagVariants();
+
// Take care of grandfathered or simple cases.
if (original === resolved) {
return original;
}
- var locales = %GetLanguageTagVariants([original, resolved]);
+ var locales = NativeJSGetLanguageTagVariants([original, resolved]);
if (locales[0].maximized !== locales[1].maximized) {
return resolved;
}
@@ -467,7 +471,8 @@ function getOptimalLanguageTag(original, resolved) {
* that is supported. This is required by the spec.
*/
function getAvailableLocalesOf(service) {
- var available = %AvailableLocalesOf(service);
+ native function NativeJSAvailableLocalesOf();
+ var available = NativeJSAvailableLocalesOf(service);
for (var i in available) {
if (available.hasOwnProperty(i)) {
diff --git a/chromium/v8/src/extensions/i18n/locale.cc b/chromium/v8/src/extensions/i18n/locale.cc
new file mode 100644
index 00000000000..6b6f9ac314d
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/locale.cc
@@ -0,0 +1,251 @@
+// 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.
+// limitations under the License.
+
+#include "locale.h"
+
+#include <string.h>
+
+#include "unicode/brkiter.h"
+#include "unicode/coll.h"
+#include "unicode/datefmt.h"
+#include "unicode/numfmt.h"
+#include "unicode/uloc.h"
+#include "unicode/uversion.h"
+
+namespace v8_i18n {
+
+void JSCanonicalizeLanguageTag(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ // Expect locale id which is a string.
+ if (args.Length() != 1 || !args[0]->IsString()) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Locale identifier, as a string, is required.")));
+ return;
+ }
+
+ UErrorCode error = U_ZERO_ERROR;
+
+ char icu_result[ULOC_FULLNAME_CAPACITY];
+ int icu_length = 0;
+
+ // Return value which denotes invalid language tag.
+ const char* const kInvalidTag = "invalid-tag";
+
+ v8::String::AsciiValue locale_id(args[0]->ToString());
+ if (*locale_id == NULL) {
+ args.GetReturnValue().Set(v8::String::New(kInvalidTag));
+ return;
+ }
+
+ uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
+ &icu_length, &error);
+ if (U_FAILURE(error) || icu_length == 0) {
+ args.GetReturnValue().Set(v8::String::New(kInvalidTag));
+ return;
+ }
+
+ char result[ULOC_FULLNAME_CAPACITY];
+
+ // Force strict BCP47 rules.
+ uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
+
+ if (U_FAILURE(error)) {
+ args.GetReturnValue().Set(v8::String::New(kInvalidTag));
+ return;
+ }
+
+ args.GetReturnValue().Set(v8::String::New(result));
+}
+
+
+void JSAvailableLocalesOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ // Expect service name which is a string.
+ if (args.Length() != 1 || !args[0]->IsString()) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Service identifier, as a string, is required.")));
+ return;
+ }
+
+ const icu::Locale* available_locales = NULL;
+
+ int32_t count = 0;
+ v8::String::AsciiValue service(args[0]->ToString());
+ if (strcmp(*service, "collator") == 0) {
+ available_locales = icu::Collator::getAvailableLocales(count);
+ } else if (strcmp(*service, "numberformat") == 0) {
+ available_locales = icu::NumberFormat::getAvailableLocales(count);
+ } else if (strcmp(*service, "dateformat") == 0) {
+ available_locales = icu::DateFormat::getAvailableLocales(count);
+ } else if (strcmp(*service, "breakiterator") == 0) {
+ available_locales = icu::BreakIterator::getAvailableLocales(count);
+ }
+
+ v8::TryCatch try_catch;
+ UErrorCode error = U_ZERO_ERROR;
+ char result[ULOC_FULLNAME_CAPACITY];
+ v8::Handle<v8::Object> locales = v8::Object::New();
+
+ for (int32_t i = 0; i < count; ++i) {
+ const char* icu_name = available_locales[i].getName();
+
+ error = U_ZERO_ERROR;
+ // No need to force strict BCP47 rules.
+ uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
+ if (U_FAILURE(error)) {
+ // This shouldn't happen, but lets not break the user.
+ continue;
+ }
+
+ // Index is just a dummy value for the property value.
+ locales->Set(v8::String::New(result), v8::Integer::New(i));
+ if (try_catch.HasCaught()) {
+ // Ignore error, but stop processing and return.
+ break;
+ }
+ }
+
+ args.GetReturnValue().Set(locales);
+}
+
+
+void JSGetDefaultICULocale(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ icu::Locale default_locale;
+
+ // Set the locale
+ char result[ULOC_FULLNAME_CAPACITY];
+ UErrorCode status = U_ZERO_ERROR;
+ uloc_toLanguageTag(
+ default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
+ if (U_SUCCESS(status)) {
+ args.GetReturnValue().Set(v8::String::New(result));
+ return;
+ }
+
+ args.GetReturnValue().Set(v8::String::New("und"));
+}
+
+
+void JSGetLanguageTagVariants(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::TryCatch try_catch;
+
+ // Expect an array of strings.
+ if (args.Length() != 1 || !args[0]->IsArray()) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Internal error. Expected Array<String>.")));
+ return;
+ }
+
+ v8::Local<v8::Array> input = v8::Local<v8::Array>::Cast(args[0]);
+ v8::Handle<v8::Array> output = v8::Array::New(input->Length());
+ for (unsigned int i = 0; i < input->Length(); ++i) {
+ v8::Local<v8::Value> locale_id = input->Get(i);
+ if (try_catch.HasCaught()) {
+ break;
+ }
+
+ if (!locale_id->IsString()) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Internal error. Array element is missing "
+ "or it isn't a string.")));
+ return;
+ }
+
+ v8::String::AsciiValue ascii_locale_id(locale_id);
+ if (*ascii_locale_id == NULL) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Internal error. Non-ASCII locale identifier.")));
+ return;
+ }
+
+ UErrorCode error = U_ZERO_ERROR;
+
+ // Convert from BCP47 to ICU format.
+ // de-DE-u-co-phonebk -> de_DE@collation=phonebook
+ char icu_locale[ULOC_FULLNAME_CAPACITY];
+ int icu_locale_length = 0;
+ uloc_forLanguageTag(*ascii_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
+ &icu_locale_length, &error);
+ if (U_FAILURE(error) || icu_locale_length == 0) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Internal error. Failed to convert locale to ICU.")));
+ return;
+ }
+
+ // Maximize the locale.
+ // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
+ char icu_max_locale[ULOC_FULLNAME_CAPACITY];
+ uloc_addLikelySubtags(
+ icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
+
+ // Remove extensions from maximized locale.
+ // de_Latn_DE@collation=phonebook -> de_Latn_DE
+ char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
+ uloc_getBaseName(
+ icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
+
+ // Get original name without extensions.
+ // de_DE@collation=phonebook -> de_DE
+ char icu_base_locale[ULOC_FULLNAME_CAPACITY];
+ uloc_getBaseName(
+ icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
+
+ // Convert from ICU locale format to BCP47 format.
+ // de_Latn_DE -> de-Latn-DE
+ char base_max_locale[ULOC_FULLNAME_CAPACITY];
+ uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
+ ULOC_FULLNAME_CAPACITY, FALSE, &error);
+
+ // de_DE -> de-DE
+ char base_locale[ULOC_FULLNAME_CAPACITY];
+ uloc_toLanguageTag(
+ icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
+
+ if (U_FAILURE(error)) {
+ v8::ThrowException(v8::Exception::SyntaxError(
+ v8::String::New("Internal error. Couldn't generate maximized "
+ "or base locale.")));
+ return;
+ }
+
+ v8::Handle<v8::Object> result = v8::Object::New();
+ result->Set(v8::String::New("maximized"), v8::String::New(base_max_locale));
+ result->Set(v8::String::New("base"), v8::String::New(base_locale));
+ if (try_catch.HasCaught()) {
+ break;
+ }
+
+ output->Set(i, result);
+ if (try_catch.HasCaught()) {
+ break;
+ }
+ }
+
+ args.GetReturnValue().Set(output);
+}
+
+} // namespace v8_i18n
diff --git a/chromium/v8/src/extensions/i18n/locale.h b/chromium/v8/src/extensions/i18n/locale.h
new file mode 100644
index 00000000000..c39568e5d9d
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/locale.h
@@ -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.
+// limitations under the License.
+
+#ifndef V8_EXTENSIONS_I18N_SRC_LOCALE_H_
+#define V8_EXTENSIONS_I18N_SRC_LOCALE_H_
+
+#include "unicode/uversion.h"
+#include "v8.h"
+
+namespace v8_i18n {
+
+// Canonicalizes the BCP47 language tag using BCP47 rules.
+// Returns 'invalid-tag' in case input was not well formed.
+void JSCanonicalizeLanguageTag(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+// Returns a list of available locales for collator, date or number formatter.
+void JSAvailableLocalesOf(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+// Returns default ICU locale.
+void JSGetDefaultICULocale(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+// Returns an array of objects, that have maximized and base names of inputs.
+// Unicode extensions are dropped from both.
+// Input: ['zh-TW-u-nu-thai', 'sr']
+// Output: [{maximized: 'zh-Hant-TW', base: 'zh-TW'},
+// {maximized: 'sr-Cyrl-RS', base: 'sr'}]
+void JSGetLanguageTagVariants(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+} // namespace v8_i18n
+
+#endif // V8_EXTENSIONS_I18N_LOCALE_H_
diff --git a/chromium/v8/src/extensions/i18n/locale.js b/chromium/v8/src/extensions/i18n/locale.js
index e4783277e64..ea95b87192e 100644
--- a/chromium/v8/src/extensions/i18n/locale.js
+++ b/chromium/v8/src/extensions/i18n/locale.js
@@ -34,6 +34,8 @@
* Canonicalizes the language tag, or throws in case the tag is invalid.
*/
function canonicalizeLanguageTag(localeID) {
+ native function NativeJSCanonicalizeLanguageTag();
+
// null is typeof 'object' so we have to do extra check.
if (typeof localeID !== 'string' && typeof localeID !== 'object' ||
localeID === null) {
@@ -50,7 +52,7 @@ function canonicalizeLanguageTag(localeID) {
// ICU bug filled - http://bugs.icu-project.org/trac/ticket/9265.
// TODO(cira): check if -u-kn-true-kc-true-kh-true still throws after
// upgrade to ICU 4.9.
- var tag = %CanonicalizeLanguageTag(localeString);
+ var tag = NativeJSCanonicalizeLanguageTag(localeString);
if (tag === 'invalid-tag') {
throw new RangeError('Invalid language tag: ' + localeString);
}
diff --git a/chromium/v8/src/extensions/i18n/number-format.cc b/chromium/v8/src/extensions/i18n/number-format.cc
new file mode 100644
index 00000000000..136471561c4
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/number-format.cc
@@ -0,0 +1,418 @@
+// 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.
+// limitations under the License.
+
+#include "number-format.h"
+
+#include <string.h>
+
+#include "i18n-utils.h"
+#include "unicode/curramt.h"
+#include "unicode/dcfmtsym.h"
+#include "unicode/decimfmt.h"
+#include "unicode/locid.h"
+#include "unicode/numfmt.h"
+#include "unicode/numsys.h"
+#include "unicode/uchar.h"
+#include "unicode/ucurr.h"
+#include "unicode/unum.h"
+#include "unicode/uversion.h"
+
+namespace v8_i18n {
+
+static icu::DecimalFormat* InitializeNumberFormat(v8::Handle<v8::String>,
+ v8::Handle<v8::Object>,
+ v8::Handle<v8::Object>);
+static icu::DecimalFormat* CreateICUNumberFormat(const icu::Locale&,
+ v8::Handle<v8::Object>);
+static void SetResolvedSettings(const icu::Locale&,
+ icu::DecimalFormat*,
+ v8::Handle<v8::Object>);
+
+icu::DecimalFormat* NumberFormat::UnpackNumberFormat(
+ v8::Handle<v8::Object> obj) {
+ v8::HandleScope handle_scope;
+
+ // v8::ObjectTemplate doesn't have HasInstance method so we can't check
+ // if obj is an instance of NumberFormat class. We'll check for a property
+ // that has to be in the object. The same applies to other services, like
+ // Collator and DateTimeFormat.
+ if (obj->HasOwnProperty(v8::String::New("numberFormat"))) {
+ return static_cast<icu::DecimalFormat*>(
+ obj->GetAlignedPointerFromInternalField(0));
+ }
+
+ return NULL;
+}
+
+void NumberFormat::DeleteNumberFormat(v8::Isolate* isolate,
+ v8::Persistent<v8::Object>* object,
+ void* param) {
+ // First delete the hidden C++ object.
+ // Unpacking should never return NULL here. That would only happen if
+ // this method is used as the weak callback for persistent handles not
+ // pointing to a date time formatter.
+ v8::HandleScope handle_scope(isolate);
+ v8::Local<v8::Object> handle = v8::Local<v8::Object>::New(isolate, *object);
+ delete UnpackNumberFormat(handle);
+
+ // Then dispose of the persistent handle to JS object.
+ object->Dispose(isolate);
+}
+
+void NumberFormat::JSInternalFormat(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsNumber()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Formatter and numeric value have to be specified.")));
+ return;
+ }
+
+ icu::DecimalFormat* number_format = UnpackNumberFormat(args[0]->ToObject());
+ if (!number_format) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("NumberFormat method called on an object "
+ "that is not a NumberFormat.")));
+ return;
+ }
+
+ // ICU will handle actual NaN value properly and return NaN string.
+ icu::UnicodeString result;
+ number_format->format(args[1]->NumberValue(), result);
+
+ args.GetReturnValue().Set(v8::String::New(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length()));
+}
+
+void NumberFormat::JSInternalParse(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsString()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Formatter and string have to be specified.")));
+ return;
+ }
+
+ icu::DecimalFormat* number_format = UnpackNumberFormat(args[0]->ToObject());
+ if (!number_format) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("NumberFormat method called on an object "
+ "that is not a NumberFormat.")));
+ return;
+ }
+
+ // ICU will handle actual NaN value properly and return NaN string.
+ icu::UnicodeString string_number;
+ if (!Utils::V8StringToUnicodeString(args[1]->ToString(), &string_number)) {
+ string_number = "";
+ }
+
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Formattable result;
+ // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
+ // to be part of Chrome.
+ // TODO(cira): Include currency parsing code using parseCurrency call.
+ // We need to check if the formatter parses all currencies or only the
+ // one it was constructed with (it will impact the API - how to return ISO
+ // code and the value).
+ number_format->parse(string_number, result, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ switch (result.getType()) {
+ case icu::Formattable::kDouble:
+ args.GetReturnValue().Set(result.getDouble());
+ return;
+ case icu::Formattable::kLong:
+ args.GetReturnValue().Set(result.getLong());
+ return;
+ case icu::Formattable::kInt64:
+ args.GetReturnValue().Set(static_cast<double>(result.getInt64()));
+ return;
+ default:
+ return;
+ }
+}
+
+void NumberFormat::JSCreateNumberFormat(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 3 ||
+ !args[0]->IsString() ||
+ !args[1]->IsObject() ||
+ !args[2]->IsObject()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Internal error, wrong parameters.")));
+ return;
+ }
+
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::ObjectTemplate> number_format_template =
+ Utils::GetTemplate(isolate);
+
+ // Create an empty object wrapper.
+ v8::Local<v8::Object> local_object = number_format_template->NewInstance();
+ // But the handle shouldn't be empty.
+ // That can happen if there was a stack overflow when creating the object.
+ if (local_object.IsEmpty()) {
+ args.GetReturnValue().Set(local_object);
+ return;
+ }
+
+ // Set number formatter as internal field of the resulting JS object.
+ icu::DecimalFormat* number_format = InitializeNumberFormat(
+ args[0]->ToString(), args[1]->ToObject(), args[2]->ToObject());
+
+ if (!number_format) {
+ v8::ThrowException(v8::Exception::Error(v8::String::New(
+ "Internal error. Couldn't create ICU number formatter.")));
+ return;
+ } else {
+ local_object->SetAlignedPointerInInternalField(0, number_format);
+
+ v8::TryCatch try_catch;
+ local_object->Set(v8::String::New("numberFormat"),
+ v8::String::New("valid"));
+ if (try_catch.HasCaught()) {
+ v8::ThrowException(v8::Exception::Error(
+ v8::String::New("Internal error, couldn't set property.")));
+ return;
+ }
+ }
+
+ v8::Persistent<v8::Object> wrapper(isolate, local_object);
+ // Make object handle weak so we can delete iterator once GC kicks in.
+ wrapper.MakeWeak<void>(NULL, &DeleteNumberFormat);
+ args.GetReturnValue().Set(wrapper);
+ wrapper.ClearAndLeak();
+}
+
+static icu::DecimalFormat* InitializeNumberFormat(
+ v8::Handle<v8::String> locale,
+ v8::Handle<v8::Object> options,
+ v8::Handle<v8::Object> resolved) {
+ // Convert BCP47 into ICU locale format.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale icu_locale;
+ char icu_result[ULOC_FULLNAME_CAPACITY];
+ int icu_length = 0;
+ v8::String::AsciiValue bcp47_locale(locale);
+ if (bcp47_locale.length() != 0) {
+ uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
+ &icu_length, &status);
+ if (U_FAILURE(status) || icu_length == 0) {
+ return NULL;
+ }
+ icu_locale = icu::Locale(icu_result);
+ }
+
+ icu::DecimalFormat* number_format =
+ CreateICUNumberFormat(icu_locale, options);
+ if (!number_format) {
+ // Remove extensions and try again.
+ icu::Locale no_extension_locale(icu_locale.getBaseName());
+ number_format = CreateICUNumberFormat(no_extension_locale, options);
+
+ // Set resolved settings (pattern, numbering system).
+ SetResolvedSettings(no_extension_locale, number_format, resolved);
+ } else {
+ SetResolvedSettings(icu_locale, number_format, resolved);
+ }
+
+ return number_format;
+}
+
+static icu::DecimalFormat* CreateICUNumberFormat(
+ const icu::Locale& icu_locale, v8::Handle<v8::Object> options) {
+ // Make formatter from options. Numbering system is added
+ // to the locale as Unicode extension (if it was specified at all).
+ UErrorCode status = U_ZERO_ERROR;
+ icu::DecimalFormat* number_format = NULL;
+ icu::UnicodeString style;
+ icu::UnicodeString currency;
+ if (Utils::ExtractStringSetting(options, "style", &style)) {
+ if (style == UNICODE_STRING_SIMPLE("currency")) {
+ Utils::ExtractStringSetting(options, "currency", &currency);
+
+ icu::UnicodeString display;
+ Utils::ExtractStringSetting(options, "currencyDisplay", &display);
+#if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
+ icu::NumberFormat::EStyles style;
+ if (display == UNICODE_STRING_SIMPLE("code")) {
+ style = icu::NumberFormat::kIsoCurrencyStyle;
+ } else if (display == UNICODE_STRING_SIMPLE("name")) {
+ style = icu::NumberFormat::kPluralCurrencyStyle;
+ } else {
+ style = icu::NumberFormat::kCurrencyStyle;
+ }
+#else // ICU version is 4.8 or above (we ignore versions below 4.0).
+ UNumberFormatStyle style;
+ if (display == UNICODE_STRING_SIMPLE("code")) {
+ style = UNUM_CURRENCY_ISO;
+ } else if (display == UNICODE_STRING_SIMPLE("name")) {
+ style = UNUM_CURRENCY_PLURAL;
+ } else {
+ style = UNUM_CURRENCY;
+ }
+#endif
+
+ number_format = static_cast<icu::DecimalFormat*>(
+ icu::NumberFormat::createInstance(icu_locale, style, status));
+ } else if (style == UNICODE_STRING_SIMPLE("percent")) {
+ number_format = static_cast<icu::DecimalFormat*>(
+ icu::NumberFormat::createPercentInstance(icu_locale, status));
+ if (U_FAILURE(status)) {
+ delete number_format;
+ return NULL;
+ }
+ // Make sure 1.1% doesn't go into 2%.
+ number_format->setMinimumFractionDigits(1);
+ } else {
+ // Make a decimal instance by default.
+ number_format = static_cast<icu::DecimalFormat*>(
+ icu::NumberFormat::createInstance(icu_locale, status));
+ }
+ }
+
+ if (U_FAILURE(status)) {
+ delete number_format;
+ return NULL;
+ }
+
+ // Set all options.
+ if (!currency.isEmpty()) {
+ number_format->setCurrency(currency.getBuffer(), status);
+ }
+
+ int32_t digits;
+ if (Utils::ExtractIntegerSetting(
+ options, "minimumIntegerDigits", &digits)) {
+ number_format->setMinimumIntegerDigits(digits);
+ }
+
+ if (Utils::ExtractIntegerSetting(
+ options, "minimumFractionDigits", &digits)) {
+ number_format->setMinimumFractionDigits(digits);
+ }
+
+ if (Utils::ExtractIntegerSetting(
+ options, "maximumFractionDigits", &digits)) {
+ number_format->setMaximumFractionDigits(digits);
+ }
+
+ bool significant_digits_used = false;
+ if (Utils::ExtractIntegerSetting(
+ options, "minimumSignificantDigits", &digits)) {
+ number_format->setMinimumSignificantDigits(digits);
+ significant_digits_used = true;
+ }
+
+ if (Utils::ExtractIntegerSetting(
+ options, "maximumSignificantDigits", &digits)) {
+ number_format->setMaximumSignificantDigits(digits);
+ significant_digits_used = true;
+ }
+
+ number_format->setSignificantDigitsUsed(significant_digits_used);
+
+ bool grouping;
+ if (Utils::ExtractBooleanSetting(options, "useGrouping", &grouping)) {
+ number_format->setGroupingUsed(grouping);
+ }
+
+ // Set rounding mode.
+ number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
+
+ return number_format;
+}
+
+static void SetResolvedSettings(const icu::Locale& icu_locale,
+ icu::DecimalFormat* number_format,
+ v8::Handle<v8::Object> resolved) {
+ icu::UnicodeString pattern;
+ number_format->toPattern(pattern);
+ resolved->Set(v8::String::New("pattern"),
+ v8::String::New(reinterpret_cast<const uint16_t*>(
+ pattern.getBuffer()), pattern.length()));
+
+ // Set resolved currency code in options.currency if not empty.
+ icu::UnicodeString currency(number_format->getCurrency());
+ if (!currency.isEmpty()) {
+ resolved->Set(v8::String::New("currency"),
+ v8::String::New(reinterpret_cast<const uint16_t*>(
+ currency.getBuffer()), currency.length()));
+ }
+
+ // Ugly hack. ICU doesn't expose numbering system in any way, so we have
+ // to assume that for given locale NumberingSystem constructor produces the
+ // same digits as NumberFormat would.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::NumberingSystem* numbering_system =
+ icu::NumberingSystem::createInstance(icu_locale, status);
+ if (U_SUCCESS(status)) {
+ const char* ns = numbering_system->getName();
+ resolved->Set(v8::String::New("numberingSystem"), v8::String::New(ns));
+ } else {
+ resolved->Set(v8::String::New("numberingSystem"), v8::Undefined());
+ }
+ delete numbering_system;
+
+ resolved->Set(v8::String::New("useGrouping"),
+ v8::Boolean::New(number_format->isGroupingUsed()));
+
+ resolved->Set(v8::String::New("minimumIntegerDigits"),
+ v8::Integer::New(number_format->getMinimumIntegerDigits()));
+
+ resolved->Set(v8::String::New("minimumFractionDigits"),
+ v8::Integer::New(number_format->getMinimumFractionDigits()));
+
+ resolved->Set(v8::String::New("maximumFractionDigits"),
+ v8::Integer::New(number_format->getMaximumFractionDigits()));
+
+ if (resolved->HasOwnProperty(v8::String::New("minimumSignificantDigits"))) {
+ resolved->Set(v8::String::New("minimumSignificantDigits"), v8::Integer::New(
+ number_format->getMinimumSignificantDigits()));
+ }
+
+ if (resolved->HasOwnProperty(v8::String::New("maximumSignificantDigits"))) {
+ resolved->Set(v8::String::New("maximumSignificantDigits"), v8::Integer::New(
+ number_format->getMaximumSignificantDigits()));
+ }
+
+ // Set the locale
+ char result[ULOC_FULLNAME_CAPACITY];
+ status = U_ZERO_ERROR;
+ uloc_toLanguageTag(
+ icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
+ if (U_SUCCESS(status)) {
+ resolved->Set(v8::String::New("locale"), v8::String::New(result));
+ } else {
+ // This would never happen, since we got the locale from ICU.
+ resolved->Set(v8::String::New("locale"), v8::String::New("und"));
+ }
+}
+
+} // namespace v8_i18n
diff --git a/chromium/v8/src/extensions/i18n/number-format.h b/chromium/v8/src/extensions/i18n/number-format.h
new file mode 100644
index 00000000000..d4dbc4d6f3b
--- /dev/null
+++ b/chromium/v8/src/extensions/i18n/number-format.h
@@ -0,0 +1,69 @@
+// 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.
+// limitations under the License.
+
+#ifndef V8_EXTENSIONS_I18N_NUMBER_FORMAT_H_
+#define V8_EXTENSIONS_I18N_NUMBER_FORMAT_H_
+
+#include "unicode/uversion.h"
+#include "v8.h"
+
+namespace U_ICU_NAMESPACE {
+class DecimalFormat;
+}
+
+namespace v8_i18n {
+
+class NumberFormat {
+ public:
+ static void JSCreateNumberFormat(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ // Helper methods for various bindings.
+
+ // Unpacks date format object from corresponding JavaScript object.
+ static icu::DecimalFormat* UnpackNumberFormat(v8::Handle<v8::Object> obj);
+
+ // Release memory we allocated for the NumberFormat once the JS object that
+ // holds the pointer gets garbage collected.
+ static void DeleteNumberFormat(v8::Isolate* isolate,
+ v8::Persistent<v8::Object>* object,
+ void* param);
+
+ // Formats number and returns corresponding string.
+ static void JSInternalFormat(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ // Parses a string and returns a number.
+ static void JSInternalParse(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ private:
+ NumberFormat();
+};
+
+} // namespace v8_i18n
+
+#endif // V8_EXTENSIONS_I18N_NUMBER_FORMAT_H_
diff --git a/chromium/v8/src/extensions/i18n/number-format.js b/chromium/v8/src/extensions/i18n/number-format.js
index 5722a5dc1f3..1cd3db13554 100644
--- a/chromium/v8/src/extensions/i18n/number-format.js
+++ b/chromium/v8/src/extensions/i18n/number-format.js
@@ -65,6 +65,8 @@ function getNumberOption(options, property, min, max, fallback) {
* Useful for subclassing.
*/
function initializeNumberFormat(numberFormat, locales, options) {
+ native function NativeJSCreateNumberFormat();
+
if (numberFormat.hasOwnProperty('__initializedIntlObject')) {
throw new TypeError('Trying to re-initialize NumberFormat object.');
}
@@ -146,9 +148,9 @@ function initializeNumberFormat(numberFormat, locales, options) {
if (internalOptions.hasOwnProperty('maximumSignificantDigits')) {
defineWEProperty(resolved, 'maximumSignificantDigits', undefined);
}
- var formatter = %CreateNumberFormat(requestedLocale,
- internalOptions,
- resolved);
+ var formatter = NativeJSCreateNumberFormat(requestedLocale,
+ internalOptions,
+ resolved);
// We can't get information about number or currency style from ICU, so we
// assume user request was fulfilled.
@@ -267,13 +269,15 @@ function initializeNumberFormat(numberFormat, locales, options) {
* NumberFormat.
*/
function formatNumber(formatter, value) {
+ native function NativeJSInternalNumberFormat();
+
// Spec treats -0 and +0 as 0.
var number = Number(value);
if (number === -0) {
number = 0;
}
- return %InternalNumberFormat(formatter.formatter, number);
+ return NativeJSInternalNumberFormat(formatter.formatter, number);
}
@@ -281,7 +285,9 @@ function formatNumber(formatter, value) {
* Returns a Number that represents string value that was passed in.
*/
function parseNumber(formatter, value) {
- return %InternalNumberParse(formatter.formatter, String(value));
+ native function NativeJSInternalNumberParse();
+
+ return NativeJSInternalNumberParse(formatter.formatter, String(value));
}
diff --git a/chromium/v8/src/factory.cc b/chromium/v8/src/factory.cc
index 9323c2f1f03..3ca0efa2107 100644
--- a/chromium/v8/src/factory.cc
+++ b/chromium/v8/src/factory.cc
@@ -1023,11 +1023,10 @@ Handle<GlobalObject> Factory::NewGlobalObject(
Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map,
- PretenureFlag pretenure,
- bool alloc_props) {
+ PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->AllocateJSObjectFromMap(*map, pretenure, alloc_props),
+ isolate()->heap()->AllocateJSObjectFromMap(*map, pretenure),
JSObject);
}
@@ -1216,7 +1215,6 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
shared->set_num_literals(literals_array_size);
if (is_generator) {
shared->set_instance_class_name(isolate()->heap()->Generator_string());
- shared->DisableOptimization(kGenerator);
}
return shared;
}
@@ -1393,10 +1391,8 @@ Handle<JSFunction> Factory::CreateApiFunction(
Smi::cast(instance_template->internal_field_count())->value();
}
- // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
- // JSObject::GetHeaderSize.
int instance_size = kPointerSize * internal_field_count;
- InstanceType type;
+ InstanceType type = INVALID_TYPE;
switch (instance_type) {
case JavaScriptObject:
type = JS_OBJECT_TYPE;
@@ -1411,10 +1407,9 @@ Handle<JSFunction> Factory::CreateApiFunction(
instance_size += JSGlobalProxy::kSize;
break;
default:
- UNREACHABLE();
- type = JS_OBJECT_TYPE; // Keep the compiler happy.
break;
}
+ ASSERT(type != INVALID_TYPE);
Handle<JSFunction> result =
NewFunction(Factory::empty_string(),
diff --git a/chromium/v8/src/factory.h b/chromium/v8/src/factory.h
index 02c9a4d2eb4..dc7933aa20f 100644
--- a/chromium/v8/src/factory.h
+++ b/chromium/v8/src/factory.h
@@ -301,11 +301,7 @@ class Factory {
// JS objects are pretenured when allocated by the bootstrapper and
// runtime.
Handle<JSObject> NewJSObjectFromMap(Handle<Map> map,
- PretenureFlag pretenure = NOT_TENURED,
- bool allocate_properties = true);
-
- Handle<JSObject> NewJSObjectFromMapForDeoptimizer(
- Handle<Map> map, PretenureFlag pretenure = NOT_TENURED);
+ PretenureFlag pretenure = NOT_TENURED);
// JS modules are pretenured.
Handle<JSModule> NewJSModule(Handle<Context> context,
diff --git a/chromium/v8/src/flag-definitions.h b/chromium/v8/src/flag-definitions.h
index c0ad4a8e17a..5fc5d880b3e 100644
--- a/chromium/v8/src/flag-definitions.h
+++ b/chromium/v8/src/flag-definitions.h
@@ -174,7 +174,6 @@ DEFINE_bool(harmony_iteration, false, "enable harmony iteration (for-of)")
DEFINE_bool(harmony_numeric_literals, false,
"enable harmony numeric literals (0o77, 0b11)")
DEFINE_bool(harmony_strings, false, "enable harmony string")
-DEFINE_bool(harmony_arrays, false, "enable harmony arrays")
DEFINE_bool(harmony, false, "enable all harmony features (except typeof)")
DEFINE_implication(harmony, harmony_scoping)
DEFINE_implication(harmony, harmony_modules)
@@ -186,7 +185,6 @@ DEFINE_implication(harmony, harmony_generators)
DEFINE_implication(harmony, harmony_iteration)
DEFINE_implication(harmony, harmony_numeric_literals)
DEFINE_implication(harmony, harmony_strings)
-DEFINE_implication(harmony, harmony_arrays)
DEFINE_implication(harmony_modules, harmony_scoping)
DEFINE_implication(harmony_observation, harmony_collections)
// TODO[dslomov] add harmony => harmony_typed_arrays
@@ -264,11 +262,10 @@ DEFINE_int(deopt_every_n_garbage_collections,
"deoptimize every n garbage collections")
DEFINE_bool(print_deopt_stress, false, "print number of possible deopt points")
DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing")
-DEFINE_bool(trap_on_stub_deopt, false,
- "put a break point before deoptimizing a stub")
DEFINE_bool(deoptimize_uncommon_cases, true, "deoptimize uncommon cases")
DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining")
DEFINE_bool(use_osr, true, "use on-stack replacement")
+DEFINE_bool(idefs, false, "use informative definitions")
DEFINE_bool(array_bounds_checks_elimination, true,
"perform array bounds checks elimination")
DEFINE_bool(array_bounds_checks_hoisting, false,
@@ -312,6 +309,9 @@ DEFINE_int(parallel_recompilation_queue_length, 8,
"the length of the parallel compilation queue")
DEFINE_int(parallel_recompilation_delay, 0,
"artificial compilation delay in ms")
+DEFINE_bool(omit_prototype_checks_for_leaf_maps, true,
+ "do not emit prototype checks if all prototypes have leaf maps, "
+ "deoptimize the optimized code if the layout of the maps changes.")
DEFINE_bool(omit_map_checks_for_leaf_maps, true,
"do not emit check maps for constant values that have a leaf map, "
"deoptimize the optimized code if the layout of the maps changes.")
diff --git a/chromium/v8/src/full-codegen.cc b/chromium/v8/src/full-codegen.cc
index f5539e8b187..6d802e965d2 100644
--- a/chromium/v8/src/full-codegen.cc
+++ b/chromium/v8/src/full-codegen.cc
@@ -512,7 +512,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
- __ Push(reg);
+ __ push(reg);
}
@@ -530,7 +530,7 @@ void FullCodeGenerator::EffectContext::PlugTOS() const {
void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
- __ Pop(result_register());
+ __ pop(result_register());
}
@@ -540,7 +540,7 @@ void FullCodeGenerator::StackValueContext::PlugTOS() const {
void FullCodeGenerator::TestContext::PlugTOS() const {
// For simplicity we always test the accumulator register.
- __ Pop(result_register());
+ __ pop(result_register());
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this);
}
@@ -1006,7 +1006,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
VisitForAccumulatorValue(left);
// We want the value in the accumulator for the test, and on the stack in
// case we need it.
- __ Push(result_register());
+ __ push(result_register());
Label discard, restore;
if (is_logical_and) {
DoTest(left, &discard, &restore, &restore);
@@ -1014,7 +1014,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
DoTest(left, &restore, &discard, &restore);
}
__ bind(&restore);
- __ Pop(result_register());
+ __ pop(result_register());
__ jmp(&done);
__ bind(&discard);
__ Drop(1);
@@ -1024,7 +1024,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
VisitForAccumulatorValue(left);
// We want the value in the accumulator for the test, and on the stack in
// case we need it.
- __ Push(result_register());
+ __ push(result_register());
Label discard;
if (is_logical_and) {
DoTest(left, &discard, &done, &discard);
@@ -1416,7 +1416,7 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// Extend the context before executing the catch block.
{ Comment cmnt(masm_, "[ Extend catch context");
__ Push(stmt->variable()->name());
- __ Push(result_register());
+ __ push(result_register());
PushFunctionArgumentForContextAllocation();
__ CallRuntime(Runtime::kPushCatchContext, 3);
StoreToFrameField(StandardFrameConstants::kContextOffset,
@@ -1481,7 +1481,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// preserved by the finally block. Call the finally block and then
// rethrow the exception if it returns.
__ Call(&finally_entry);
- __ Push(result_register());
+ __ push(result_register());
__ CallRuntime(Runtime::kReThrow, 1);
// Finally block implementation.
diff --git a/chromium/v8/src/full-codegen.h b/chromium/v8/src/full-codegen.h
index af63aedfbff..a9db54e32c1 100644
--- a/chromium/v8/src/full-codegen.h
+++ b/chromium/v8/src/full-codegen.h
@@ -31,14 +31,11 @@
#include "v8.h"
#include "allocation.h"
-#include "assert-scope.h"
#include "ast.h"
#include "code-stubs.h"
#include "codegen.h"
#include "compiler.h"
#include "data-flow.h"
-#include "globals.h"
-#include "objects.h"
namespace v8 {
namespace internal {
@@ -139,64 +136,7 @@ class FullCodeGenerator: public AstVisitor {
#error Unsupported target architecture.
#endif
- class BackEdgeTableIterator {
- public:
- explicit BackEdgeTableIterator(Code* unoptimized) {
- ASSERT(unoptimized->kind() == Code::FUNCTION);
- instruction_start_ = unoptimized->instruction_start();
- cursor_ = instruction_start_ + unoptimized->back_edge_table_offset();
- ASSERT(cursor_ < instruction_start_ + unoptimized->instruction_size());
- table_length_ = Memory::uint32_at(cursor_);
- cursor_ += kTableLengthSize;
- end_ = cursor_ + table_length_ * kEntrySize;
- }
-
- bool Done() { return cursor_ >= end_; }
-
- void Next() {
- ASSERT(!Done());
- cursor_ += kEntrySize;
- }
-
- BailoutId ast_id() {
- ASSERT(!Done());
- return BailoutId(static_cast<int>(
- Memory::uint32_at(cursor_ + kAstIdOffset)));
- }
-
- uint32_t loop_depth() {
- ASSERT(!Done());
- return Memory::uint32_at(cursor_ + kLoopDepthOffset);
- }
-
- uint32_t pc_offset() {
- ASSERT(!Done());
- return Memory::uint32_at(cursor_ + kPcOffsetOffset);
- }
-
- Address pc() {
- ASSERT(!Done());
- return instruction_start_ + pc_offset();
- }
-
- uint32_t table_length() { return table_length_; }
-
- private:
- static const int kTableLengthSize = kIntSize;
- static const int kAstIdOffset = 0 * kIntSize;
- static const int kPcOffsetOffset = 1 * kIntSize;
- static const int kLoopDepthOffset = 2 * kIntSize;
- static const int kEntrySize = 3 * kIntSize;
-
- Address cursor_;
- Address end_;
- Address instruction_start_;
- uint32_t table_length_;
- DisallowHeapAllocation no_gc_while_iterating_over_raw_addresses_;
-
- DISALLOW_COPY_AND_ASSIGN(BackEdgeTableIterator);
- };
-
+ static const int kBackEdgeEntrySize = 3 * kIntSize;
private:
class Breakable;
@@ -685,6 +625,8 @@ class FullCodeGenerator: public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
+ void EmitUnaryOperation(UnaryOperation* expr, const char* comment);
+
void VisitComma(BinaryOperation* expr);
void VisitLogicalExpression(BinaryOperation* expr);
void VisitArithmeticExpression(BinaryOperation* expr);
diff --git a/chromium/v8/src/global-handles.cc b/chromium/v8/src/global-handles.cc
index 5df9dd4c6c7..41771e6db41 100644
--- a/chromium/v8/src/global-handles.cc
+++ b/chromium/v8/src/global-handles.cc
@@ -1019,68 +1019,4 @@ void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() {
}
-EternalHandles::EternalHandles() : size_(0) {
- STATIC_ASSERT(v8::kUninitializedEternalIndex == kInvalidIndex);
- for (unsigned i = 0; i < ARRAY_SIZE(singleton_handles_); i++) {
- singleton_handles_[i] = kInvalidIndex;
- }
-}
-
-
-EternalHandles::~EternalHandles() {
- for (int i = 0; i < blocks_.length(); i++) delete[] blocks_[i];
-}
-
-
-void EternalHandles::IterateAllRoots(ObjectVisitor* visitor) {
- int limit = size_;
- for (int i = 0; i < blocks_.length(); i++) {
- ASSERT(limit > 0);
- Object** block = blocks_[i];
- visitor->VisitPointers(block, block + Min(limit, kSize));
- limit -= kSize;
- }
-}
-
-
-void EternalHandles::IterateNewSpaceRoots(ObjectVisitor* visitor) {
- for (int i = 0; i < new_space_indices_.length(); i++) {
- visitor->VisitPointer(GetLocation(new_space_indices_[i]));
- }
-}
-
-
-void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) {
- int last = 0;
- for (int i = 0; i < new_space_indices_.length(); i++) {
- int index = new_space_indices_[i];
- if (heap->InNewSpace(*GetLocation(index))) {
- new_space_indices_[last++] = index;
- }
- }
- new_space_indices_.Rewind(last);
-}
-
-
-int EternalHandles::Create(Isolate* isolate, Object* object) {
- if (object == NULL) return kInvalidIndex;
- ASSERT_NE(isolate->heap()->the_hole_value(), object);
- int block = size_ >> kShift;
- int offset = size_ & kMask;
- // need to resize
- if (offset == 0) {
- Object** next_block = new Object*[kSize];
- Object* the_hole = isolate->heap()->the_hole_value();
- MemsetPointer(next_block, the_hole, kSize);
- blocks_.Add(next_block);
- }
- ASSERT_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]);
- blocks_[block][offset] = object;
- if (isolate->heap()->InNewSpace(object)) {
- new_space_indices_.Add(size_);
- }
- return size_++;
-}
-
-
} } // namespace v8::internal
diff --git a/chromium/v8/src/global-handles.h b/chromium/v8/src/global-handles.h
index 5a4ad13e2f5..cd75133a243 100644
--- a/chromium/v8/src/global-handles.h
+++ b/chromium/v8/src/global-handles.h
@@ -31,7 +31,6 @@
#include "../include/v8.h"
#include "../include/v8-profiler.h"
-#include "handles.h"
#include "list.h"
#include "v8utils.h"
@@ -332,76 +331,6 @@ class GlobalHandles {
};
-class EternalHandles {
- public:
- enum SingletonHandle {
- I18N_TEMPLATE_ONE,
- I18N_TEMPLATE_TWO,
-
- NUMBER_OF_SINGLETON_HANDLES
- };
-
- EternalHandles();
- ~EternalHandles();
-
- int NumberOfHandles() { return size_; }
-
- // Create an EternalHandle, returning the index.
- int Create(Isolate* isolate, Object* object);
-
- // Grab the handle for an existing EternalHandle.
- inline Handle<Object> Get(int index) {
- return Handle<Object>(GetLocation(index));
- }
-
- // Grab the handle for an existing SingletonHandle.
- inline Handle<Object> GetSingleton(SingletonHandle singleton) {
- ASSERT(Exists(singleton));
- return Get(singleton_handles_[singleton]);
- }
-
- // Checks whether a SingletonHandle has been assigned.
- inline bool Exists(SingletonHandle singleton) {
- return singleton_handles_[singleton] != kInvalidIndex;
- }
-
- // Assign a SingletonHandle to an empty slot and returns the handle.
- Handle<Object> CreateSingleton(Isolate* isolate,
- Object* object,
- SingletonHandle singleton) {
- ASSERT(singleton_handles_[singleton] == kInvalidIndex);
- singleton_handles_[singleton] = Create(isolate, object);
- return Get(singleton_handles_[singleton]);
- }
-
- // Iterates over all handles.
- void IterateAllRoots(ObjectVisitor* visitor);
- // Iterates over all handles which might be in new space.
- void IterateNewSpaceRoots(ObjectVisitor* visitor);
- // Rebuilds new space list.
- void PostGarbageCollectionProcessing(Heap* heap);
-
- private:
- static const int kInvalidIndex = -1;
- static const int kShift = 8;
- static const int kSize = 1 << kShift;
- static const int kMask = 0xff;
-
- // Gets the slot for an index
- inline Object** GetLocation(int index) {
- ASSERT(index >= 0 && index < size_);
- return &blocks_[index >> kShift][index & kMask];
- }
-
- int size_;
- List<Object**> blocks_;
- List<int> new_space_indices_;
- int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
-
- DISALLOW_COPY_AND_ASSIGN(EternalHandles);
-};
-
-
} } // namespace v8::internal
#endif // V8_GLOBAL_HANDLES_H_
diff --git a/chromium/v8/src/harmony-array.js b/chromium/v8/src/harmony-array.js
deleted file mode 100644
index e440299ff61..00000000000
--- a/chromium/v8/src/harmony-array.js
+++ /dev/null
@@ -1,124 +0,0 @@
-// 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';
-
-// This file relies on the fact that the following declaration has been made
-// in runtime.js:
-// var $Array = global.Array;
-
-// -------------------------------------------------------------------
-
-// ES6 draft 07-15-13, section 15.4.3.23
-function ArrayFind(predicate /* thisArg */) { // length == 1
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["Array.prototype.find"]);
- }
-
- var array = ToObject(this);
- var length = ToInteger(array.length);
-
- if (!IS_SPEC_FUNCTION(predicate)) {
- throw MakeTypeError('called_non_callable', [predicate]);
- }
-
- var thisArg;
- if (%_ArgumentsLength() > 1) {
- thisArg = %_Arguments(1);
- }
-
- if (IS_NULL_OR_UNDEFINED(thisArg)) {
- thisArg = %GetDefaultReceiver(predicate) || thisArg;
- } else if (!IS_SPEC_OBJECT(thisArg) && %IsClassicModeFunction(predicate)) {
- thisArg = ToObject(thisArg);
- }
-
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- if (%_CallFunction(thisArg, element, i, array, predicate)) {
- return element;
- }
- }
- }
-
- return;
-}
-
-
-// ES6 draft 07-15-13, section 15.4.3.24
-function ArrayFindIndex(predicate /* thisArg */) { // length == 1
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["Array.prototype.findIndex"]);
- }
-
- var array = ToObject(this);
- var length = ToInteger(array.length);
-
- if (!IS_SPEC_FUNCTION(predicate)) {
- throw MakeTypeError('called_non_callable', [predicate]);
- }
-
- var thisArg;
- if (%_ArgumentsLength() > 1) {
- thisArg = %_Arguments(1);
- }
-
- if (IS_NULL_OR_UNDEFINED(thisArg)) {
- thisArg = %GetDefaultReceiver(predicate) || thisArg;
- } else if (!IS_SPEC_OBJECT(thisArg) && %IsClassicModeFunction(predicate)) {
- thisArg = ToObject(thisArg);
- }
-
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- if (%_CallFunction(thisArg, element, i, array, predicate)) {
- return i;
- }
- }
- }
-
- return -1;
-}
-
-
-// -------------------------------------------------------------------
-
-function HarmonyArrayExtendArrayPrototype() {
- %CheckIsBootstrapping();
-
- // Set up the non-enumerable functions on the Array prototype object.
- InstallFunctions($Array.prototype, DONT_ENUM, $Array(
- "find", ArrayFind,
- "findIndex", ArrayFindIndex
- ));
-}
-
-HarmonyArrayExtendArrayPrototype(); \ No newline at end of file
diff --git a/chromium/v8/src/heap-snapshot-generator.cc b/chromium/v8/src/heap-snapshot-generator.cc
index 1c8a7b3dc4d..9f9f84a01dc 100644
--- a/chromium/v8/src/heap-snapshot-generator.cc
+++ b/chromium/v8/src/heap-snapshot-generator.cc
@@ -369,12 +369,6 @@ const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId =
HeapObjectsMap::kGcRootsFirstSubrootId +
VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep;
-
-static bool AddressesMatch(void* key1, void* key2) {
- return key1 == key2;
-}
-
-
HeapObjectsMap::HeapObjectsMap(Heap* heap)
: next_id_(kFirstAvailableObjectId),
entries_map_(AddressesMatch),
@@ -399,20 +393,19 @@ void HeapObjectsMap::MoveObject(Address from, Address to) {
ASSERT(to != NULL);
ASSERT(from != NULL);
if (from == to) return;
- void* from_value = entries_map_.Remove(from, ComputePointerHash(from));
+ void* from_value = entries_map_.Remove(from, AddressHash(from));
if (from_value == NULL) {
// It may occur that some untracked object moves to an address X and there
// is a tracked object at that address. In this case we should remove the
// entry as we know that the object has died.
- void* to_value = entries_map_.Remove(to, ComputePointerHash(to));
+ void* to_value = entries_map_.Remove(to, AddressHash(to));
if (to_value != NULL) {
int to_entry_info_index =
static_cast<int>(reinterpret_cast<intptr_t>(to_value));
entries_.at(to_entry_info_index).addr = NULL;
}
} else {
- HashMap::Entry* to_entry = entries_map_.Lookup(to, ComputePointerHash(to),
- true);
+ HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true);
if (to_entry->value != NULL) {
// We found the existing entry with to address for an old object.
// Without this operation we will have two EntryInfo's with the same
@@ -432,8 +425,7 @@ void HeapObjectsMap::MoveObject(Address from, Address to) {
SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
- HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr),
- false);
+ HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false);
if (entry == NULL) return 0;
int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
EntryInfo& entry_info = entries_.at(entry_index);
@@ -445,8 +437,7 @@ SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr,
unsigned int size) {
ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
- HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr),
- true);
+ HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true);
if (entry->value != NULL) {
int entry_index =
static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
@@ -541,14 +532,13 @@ void HeapObjectsMap::RemoveDeadEntries() {
}
entries_.at(first_free_entry).accessed = false;
HashMap::Entry* entry = entries_map_.Lookup(
- entry_info.addr, ComputePointerHash(entry_info.addr), false);
+ entry_info.addr, AddressHash(entry_info.addr), false);
ASSERT(entry);
entry->value = reinterpret_cast<void*>(first_free_entry);
++first_free_entry;
} else {
if (entry_info.addr) {
- entries_map_.Remove(entry_info.addr,
- ComputePointerHash(entry_info.addr));
+ entries_map_.Remove(entry_info.addr, AddressHash(entry_info.addr));
}
}
}
diff --git a/chromium/v8/src/heap-snapshot-generator.h b/chromium/v8/src/heap-snapshot-generator.h
index cea995820f7..31d808856d1 100644
--- a/chromium/v8/src/heap-snapshot-generator.h
+++ b/chromium/v8/src/heap-snapshot-generator.h
@@ -266,6 +266,16 @@ class HeapObjectsMap {
void UpdateHeapObjectsMap();
void RemoveDeadEntries();
+ static bool AddressesMatch(void* key1, void* key2) {
+ return key1 == key2;
+ }
+
+ static uint32_t AddressHash(Address addr) {
+ return ComputeIntegerHash(
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)),
+ v8::internal::kZeroHashSeed);
+ }
+
SnapshotObjectId next_id_;
HashMap entries_map_;
List<EntryInfo> entries_;
diff --git a/chromium/v8/src/heap.cc b/chromium/v8/src/heap.cc
index 9d8a6fad995..c2a2707602e 100644
--- a/chromium/v8/src/heap.cc
+++ b/chromium/v8/src/heap.cc
@@ -703,16 +703,6 @@ bool Heap::CollectGarbage(AllocationSpace space,
}
-int Heap::NotifyContextDisposed() {
- if (FLAG_parallel_recompilation) {
- // Flush the queued recompilation tasks.
- isolate()->optimizing_compiler_thread()->Flush();
- }
- flush_monomorphic_ics_ = true;
- return ++contexts_disposed_;
-}
-
-
void Heap::PerformScavenge() {
GCTracer tracer(this, NULL, NULL);
if (incremental_marking()->IsStopped()) {
@@ -1024,8 +1014,6 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
}
gc_post_processing_depth_--;
- isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
-
// Update relocatables.
Relocatable::PostGarbageCollectionProcessing();
@@ -2018,6 +2006,7 @@ class ScavengingVisitor : public StaticVisitorBase {
private:
enum ObjectContents { DATA_OBJECT, POINTER_OBJECT };
+ enum SizeRestriction { SMALL, UNKNOWN_SIZE };
static void RecordCopiedObject(Heap* heap, HeapObject* obj) {
bool should_record = false;
@@ -2069,12 +2058,15 @@ class ScavengingVisitor : public StaticVisitorBase {
}
- template<ObjectContents object_contents, int alignment>
+ template<ObjectContents object_contents,
+ SizeRestriction size_restriction,
+ int alignment>
static inline void EvacuateObject(Map* map,
HeapObject** slot,
HeapObject* object,
int object_size) {
- SLOW_ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
+ SLOW_ASSERT((size_restriction != SMALL) ||
+ (object_size <= Page::kMaxNonCodeHeapObjectSize));
SLOW_ASSERT(object->Size() == object_size);
int allocation_size = object_size;
@@ -2087,11 +2079,17 @@ class ScavengingVisitor : public StaticVisitorBase {
if (heap->ShouldBePromoted(object->address(), object_size)) {
MaybeObject* maybe_result;
- if (object_contents == DATA_OBJECT) {
- maybe_result = heap->old_data_space()->AllocateRaw(allocation_size);
+ if ((size_restriction != SMALL) &&
+ (allocation_size > Page::kMaxNonCodeHeapObjectSize)) {
+ maybe_result = heap->lo_space()->AllocateRaw(allocation_size,
+ NOT_EXECUTABLE);
} else {
- maybe_result =
- heap->old_pointer_space()->AllocateRaw(allocation_size);
+ if (object_contents == DATA_OBJECT) {
+ maybe_result = heap->old_data_space()->AllocateRaw(allocation_size);
+ } else {
+ maybe_result =
+ heap->old_pointer_space()->AllocateRaw(allocation_size);
+ }
}
Object* result = NULL; // Initialization to please compiler.
@@ -2165,8 +2163,10 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject** slot,
HeapObject* object) {
int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
- EvacuateObject<POINTER_OBJECT, kObjectAlignment>(
- map, slot, object, object_size);
+ EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(map,
+ slot,
+ object,
+ object_size);
}
@@ -2175,8 +2175,11 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject* object) {
int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
int object_size = FixedDoubleArray::SizeFor(length);
- EvacuateObject<DATA_OBJECT, kDoubleAlignment>(
- map, slot, object, object_size);
+ EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kDoubleAlignment>(
+ map,
+ slot,
+ object,
+ object_size);
}
@@ -2184,7 +2187,7 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject** slot,
HeapObject* object) {
int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
- EvacuateObject<DATA_OBJECT, kObjectAlignment>(
+ EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(
map, slot, object, object_size);
}
@@ -2194,7 +2197,7 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject* object) {
int object_size = SeqOneByteString::cast(object)->
SeqOneByteStringSize(map->instance_type());
- EvacuateObject<DATA_OBJECT, kObjectAlignment>(
+ EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(
map, slot, object, object_size);
}
@@ -2204,7 +2207,7 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject* object) {
int object_size = SeqTwoByteString::cast(object)->
SeqTwoByteStringSize(map->instance_type());
- EvacuateObject<DATA_OBJECT, kObjectAlignment>(
+ EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(
map, slot, object, object_size);
}
@@ -2248,7 +2251,7 @@ class ScavengingVisitor : public StaticVisitorBase {
}
int object_size = ConsString::kSize;
- EvacuateObject<POINTER_OBJECT, kObjectAlignment>(
+ EvacuateObject<POINTER_OBJECT, SMALL, kObjectAlignment>(
map, slot, object, object_size);
}
@@ -2259,7 +2262,7 @@ class ScavengingVisitor : public StaticVisitorBase {
static inline void VisitSpecialized(Map* map,
HeapObject** slot,
HeapObject* object) {
- EvacuateObject<object_contents, kObjectAlignment>(
+ EvacuateObject<object_contents, SMALL, kObjectAlignment>(
map, slot, object, object_size);
}
@@ -2267,7 +2270,7 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject** slot,
HeapObject* object) {
int object_size = map->instance_size();
- EvacuateObject<object_contents, kObjectAlignment>(
+ EvacuateObject<object_contents, SMALL, kObjectAlignment>(
map, slot, object, object_size);
}
};
@@ -3215,6 +3218,9 @@ bool Heap::CreateInitialObjects() {
}
set_observed_symbol(Symbol::cast(obj));
+ set_i18n_template_one(the_hole_value());
+ set_i18n_template_two(the_hole_value());
+
// Handling of script id generation is in Factory::NewScript.
set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId));
@@ -3263,12 +3269,6 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
}
-bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) {
- return !RootCanBeWrittenAfterInitialization(root_index) &&
- !InNewSpace(roots_array_start()[root_index]);
-}
-
-
Object* RegExpResultsCache::Lookup(Heap* heap,
String* key_string,
Object* key_pattern,
@@ -4481,8 +4481,7 @@ void Heap::InitializeJSObjectFromMap(JSObject* obj,
}
-MaybeObject* Heap::AllocateJSObjectFromMap(
- Map* map, PretenureFlag pretenure, bool allocate_properties) {
+MaybeObject* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) {
// JSFunctions should be allocated using AllocateFunction to be
// properly initialized.
ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
@@ -4493,15 +4492,11 @@ MaybeObject* Heap::AllocateJSObjectFromMap(
ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
// Allocate the backing storage for the properties.
- FixedArray* properties;
- if (allocate_properties) {
- int prop_size = map->InitialPropertiesLength();
- ASSERT(prop_size >= 0);
- { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, pretenure);
- if (!maybe_properties->To(&properties)) return maybe_properties;
- }
- } else {
- properties = empty_fixed_array();
+ int prop_size = map->InitialPropertiesLength();
+ ASSERT(prop_size >= 0);
+ Object* properties;
+ { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, pretenure);
+ if (!maybe_properties->ToObject(&properties)) return maybe_properties;
}
// Allocate the JSObject.
@@ -4513,15 +4508,17 @@ MaybeObject* Heap::AllocateJSObjectFromMap(
if (!maybe_obj->To(&obj)) return maybe_obj;
// Initialize the JSObject.
- InitializeJSObjectFromMap(JSObject::cast(obj), properties, map);
+ InitializeJSObjectFromMap(JSObject::cast(obj),
+ FixedArray::cast(properties),
+ map);
ASSERT(JSObject::cast(obj)->HasFastElements() ||
JSObject::cast(obj)->HasExternalArrayElements());
return obj;
}
-MaybeObject* Heap::AllocateJSObjectFromMapWithAllocationSite(
- Map* map, Handle<AllocationSite> allocation_site) {
+MaybeObject* Heap::AllocateJSObjectFromMapWithAllocationSite(Map* map,
+ Handle<AllocationSite> allocation_site) {
// JSFunctions should be allocated using AllocateFunction to be
// properly initialized.
ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
@@ -4534,9 +4531,9 @@ MaybeObject* Heap::AllocateJSObjectFromMapWithAllocationSite(
// Allocate the backing storage for the properties.
int prop_size = map->InitialPropertiesLength();
ASSERT(prop_size >= 0);
- FixedArray* properties;
+ Object* properties;
{ MaybeObject* maybe_properties = AllocateFixedArray(prop_size);
- if (!maybe_properties->To(&properties)) return maybe_properties;
+ if (!maybe_properties->ToObject(&properties)) return maybe_properties;
}
// Allocate the JSObject.
@@ -4548,7 +4545,9 @@ MaybeObject* Heap::AllocateJSObjectFromMapWithAllocationSite(
if (!maybe_obj->To(&obj)) return maybe_obj;
// Initialize the JSObject.
- InitializeJSObjectFromMap(JSObject::cast(obj), properties, map);
+ InitializeJSObjectFromMap(JSObject::cast(obj),
+ FixedArray::cast(properties),
+ map);
ASSERT(JSObject::cast(obj)->HasFastElements());
return obj;
}
@@ -6609,14 +6608,6 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
}
v->Synchronize(VisitorSynchronization::kGlobalHandles);
- // Iterate over eternal handles.
- if (mode == VISIT_ALL_IN_SCAVENGE) {
- isolate_->eternal_handles()->IterateNewSpaceRoots(v);
- } else {
- isolate_->eternal_handles()->IterateAllRoots(v);
- }
- v->Synchronize(VisitorSynchronization::kEternalHandles);
-
// Iterate over pointers being held by inactive threads.
isolate_->thread_manager()->Iterate(v);
v->Synchronize(VisitorSynchronization::kThreadManager);
diff --git a/chromium/v8/src/heap.h b/chromium/v8/src/heap.h
index 78c0e5b26b4..672b8c16325 100644
--- a/chromium/v8/src/heap.h
+++ b/chromium/v8/src/heap.h
@@ -189,7 +189,9 @@ namespace internal {
V(Symbol, elements_transition_symbol, ElementsTransitionSymbol) \
V(SeededNumberDictionary, empty_slow_element_dictionary, \
EmptySlowElementDictionary) \
- V(Symbol, observed_symbol, ObservedSymbol)
+ V(Symbol, observed_symbol, ObservedSymbol) \
+ V(HeapObject, i18n_template_one, I18nTemplateOne) \
+ V(HeapObject, i18n_template_two, I18nTemplateTwo)
#define ROOT_LIST(V) \
STRONG_ROOT_LIST(V) \
@@ -736,7 +738,7 @@ class Heap {
// failed.
// Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateJSObjectFromMap(
- Map* map, PretenureFlag pretenure = NOT_TENURED, bool alloc_props = true);
+ Map* map, PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT MaybeObject* AllocateJSObjectFromMapWithAllocationSite(
Map* map, Handle<AllocationSite> allocation_site);
@@ -1254,7 +1256,10 @@ class Heap {
void EnsureHeapIsIterable();
// Notify the heap that a context has been disposed.
- int NotifyContextDisposed();
+ int NotifyContextDisposed() {
+ flush_monomorphic_ics_ = true;
+ return ++contexts_disposed_;
+ }
// Utility to invoke the scavenger. This is needed in test code to
// ensure correct callback for weak global handles.
@@ -1297,6 +1302,12 @@ class Heap {
ASSERT((callback == NULL) ^ (global_gc_epilogue_callback_ == NULL));
global_gc_epilogue_callback_ = callback;
}
+ void SetI18nTemplateOne(ObjectTemplateInfo* tmpl) {
+ set_i18n_template_one(tmpl);
+ }
+ void SetI18nTemplateTwo(ObjectTemplateInfo* tmpl) {
+ set_i18n_template_two(tmpl);
+ }
// Heap root getters. We have versions with and without type::cast() here.
// You can't use type::cast during GC because the assert fails.
@@ -1615,8 +1626,6 @@ class Heap {
// Generated code can embed direct references to non-writable roots if
// they are in new space.
static bool RootCanBeWrittenAfterInitialization(RootListIndex root_index);
- // Generated code can treat direct references to this root as constant.
- bool RootCanBeTreatedAsConstant(RootListIndex root_index);
MUST_USE_RESULT MaybeObject* NumberToString(
Object* number, bool check_number_string_cache = true,
diff --git a/chromium/v8/src/hydrogen-escape-analysis.cc b/chromium/v8/src/hydrogen-escape-analysis.cc
index 0359678ef95..961bb94e9c1 100644
--- a/chromium/v8/src/hydrogen-escape-analysis.cc
+++ b/chromium/v8/src/hydrogen-escape-analysis.cc
@@ -63,234 +63,4 @@ void HEscapeAnalysisPhase::CollectCapturedValues() {
}
-HCapturedObject* HEscapeAnalysisPhase::NewState(HInstruction* previous) {
- Zone* zone = graph()->zone();
- HCapturedObject* state = new(zone) HCapturedObject(number_of_values_, zone);
- state->InsertAfter(previous);
- return state;
-}
-
-
-// Create a new state for replacing HAllocate instructions.
-HCapturedObject* HEscapeAnalysisPhase::NewStateForAllocation(
- HInstruction* previous) {
- HConstant* undefined = graph()->GetConstantUndefined();
- HCapturedObject* state = NewState(previous);
- for (int index = 0; index < number_of_values_; index++) {
- state->SetOperandAt(index, undefined);
- }
- return state;
-}
-
-
-// Create a new state full of phis for loop header entries.
-HCapturedObject* HEscapeAnalysisPhase::NewStateForLoopHeader(
- HInstruction* previous, HCapturedObject* old_state) {
- HBasicBlock* block = previous->block();
- HCapturedObject* state = NewState(previous);
- for (int index = 0; index < number_of_values_; index++) {
- HValue* operand = old_state->OperandAt(index);
- HPhi* phi = NewPhiAndInsert(block, operand, index);
- state->SetOperandAt(index, phi);
- }
- return state;
-}
-
-
-// Create a new state by copying an existing one.
-HCapturedObject* HEscapeAnalysisPhase::NewStateCopy(
- HInstruction* previous, HCapturedObject* old_state) {
- HCapturedObject* state = NewState(previous);
- for (int index = 0; index < number_of_values_; index++) {
- HValue* operand = old_state->OperandAt(index);
- state->SetOperandAt(index, operand);
- }
- return state;
-}
-
-
-// Insert a newly created phi into the given block and fill all incoming
-// edges with the given value.
-HPhi* HEscapeAnalysisPhase::NewPhiAndInsert(
- HBasicBlock* block, HValue* incoming_value, int index) {
- Zone* zone = graph()->zone();
- HPhi* phi = new(zone) HPhi(HPhi::kInvalidMergedIndex, zone);
- for (int i = 0; i < block->predecessors()->length(); i++) {
- phi->AddInput(incoming_value);
- }
- block->AddPhi(phi);
- return phi;
-}
-
-
-// Performs a forward data-flow analysis of all loads and stores on the
-// given captured allocation. This uses a reverse post-order iteration
-// over affected basic blocks. All non-escaping instructions are handled
-// and replaced during the analysis.
-void HEscapeAnalysisPhase::AnalyzeDataFlow(HInstruction* allocate) {
- HBasicBlock* allocate_block = allocate->block();
- block_states_.AddBlock(NULL, graph()->blocks()->length(), zone());
-
- // Iterate all blocks starting with the allocation block, since the
- // allocation cannot dominate blocks that come before.
- int start = allocate_block->block_id();
- for (int i = start; i < graph()->blocks()->length(); i++) {
- HBasicBlock* block = graph()->blocks()->at(i);
- HCapturedObject* state = StateAt(block);
-
- // Skip blocks that are not dominated by the captured allocation.
- if (!allocate_block->Dominates(block) && allocate_block != block) continue;
- if (FLAG_trace_escape_analysis) {
- PrintF("Analyzing data-flow in B%d\n", block->block_id());
- }
-
- // Go through all instructions of the current block.
- for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- switch (instr->opcode()) {
- case HValue::kAllocate: {
- if (instr != allocate) continue;
- state = NewStateForAllocation(allocate);
- break;
- }
- case HValue::kLoadNamedField: {
- HLoadNamedField* load = HLoadNamedField::cast(instr);
- int index = load->access().offset() / kPointerSize;
- if (load->object() != allocate) continue;
- ASSERT(load->access().IsInobject());
- HValue* replacement = state->OperandAt(index);
- load->DeleteAndReplaceWith(replacement);
- if (FLAG_trace_escape_analysis) {
- PrintF("Replacing load #%d with #%d (%s)\n", instr->id(),
- replacement->id(), replacement->Mnemonic());
- }
- break;
- }
- case HValue::kStoreNamedField: {
- HStoreNamedField* store = HStoreNamedField::cast(instr);
- int index = store->access().offset() / kPointerSize;
- if (store->object() != allocate) continue;
- ASSERT(store->access().IsInobject());
- state = NewStateCopy(store, state);
- state->SetOperandAt(index, store->value());
- if (store->has_transition()) {
- state->SetOperandAt(0, store->transition());
- }
- store->DeleteAndReplaceWith(NULL);
- if (FLAG_trace_escape_analysis) {
- PrintF("Replacing store #%d%s\n", instr->id(),
- store->has_transition() ? " (with transition)" : "");
- }
- break;
- }
- case HValue::kSimulate: {
- HSimulate* simulate = HSimulate::cast(instr);
- // TODO(mstarzinger): This doesn't track deltas for values on the
- // operand stack yet. Find a repro test case and fix this.
- for (int i = 0; i < simulate->OperandCount(); i++) {
- if (simulate->OperandAt(i) != allocate) continue;
- simulate->SetOperandAt(i, state);
- }
- break;
- }
- case HValue::kArgumentsObject:
- case HValue::kCapturedObject: {
- for (int i = 0; i < instr->OperandCount(); i++) {
- if (instr->OperandAt(i) != allocate) continue;
- instr->SetOperandAt(i, state);
- }
- break;
- }
- case HValue::kCheckHeapObject: {
- HCheckHeapObject* check = HCheckHeapObject::cast(instr);
- if (check->value() != allocate) continue;
- check->DeleteAndReplaceWith(NULL);
- break;
- }
- case HValue::kCheckMaps: {
- HCheckMaps* mapcheck = HCheckMaps::cast(instr);
- if (mapcheck->value() != allocate) continue;
- // TODO(mstarzinger): This approach breaks if the tracked map value
- // is not a HConstant. Find a repro test case and fix this.
- for (HUseIterator it(mapcheck->uses()); !it.Done(); it.Advance()) {
- if (!it.value()->IsLoadNamedField()) continue;
- HLoadNamedField* load = HLoadNamedField::cast(it.value());
- ASSERT(load->typecheck() == mapcheck);
- load->ClearTypeCheck();
- }
- ASSERT(mapcheck->HasNoUses());
-
- mapcheck->DeleteAndReplaceWith(NULL);
- break;
- }
- default:
- // Nothing to see here, move along ...
- break;
- }
- }
-
- // Propagate the block state forward to all successor blocks.
- for (int i = 0; i < block->end()->SuccessorCount(); i++) {
- HBasicBlock* succ = block->end()->SuccessorAt(i);
- if (!allocate_block->Dominates(succ)) continue;
- if (succ->predecessors()->length() == 1) {
- // Case 1: This is the only predecessor, just reuse state.
- SetStateAt(succ, state);
- } else if (StateAt(succ) == NULL && succ->IsLoopHeader()) {
- // Case 2: This is a state that enters a loop header, be
- // pessimistic about loop headers, add phis for all values.
- SetStateAt(succ, NewStateForLoopHeader(succ->first(), state));
- } else if (StateAt(succ) == NULL) {
- // Case 3: This is the first state propagated forward to the
- // successor, leave a copy of the current state.
- SetStateAt(succ, NewStateCopy(succ->first(), state));
- } else {
- // Case 4: This is a state that needs merging with previously
- // propagated states, potentially introducing new phis lazily or
- // adding values to existing phis.
- HCapturedObject* succ_state = StateAt(succ);
- for (int index = 0; index < number_of_values_; index++) {
- HValue* operand = state->OperandAt(index);
- HValue* succ_operand = succ_state->OperandAt(index);
- if (succ_operand->IsPhi() && succ_operand->block() == succ) {
- // Phi already exists, add operand.
- HPhi* phi = HPhi::cast(succ_operand);
- phi->SetOperandAt(succ->PredecessorIndexOf(block), operand);
- } else if (succ_operand != operand) {
- // Phi does not exist, introduce one.
- HPhi* phi = NewPhiAndInsert(succ, succ_operand, index);
- phi->SetOperandAt(succ->PredecessorIndexOf(block), operand);
- succ_state->SetOperandAt(index, phi);
- }
- }
- }
- }
- }
-
- // All uses have been handled.
- ASSERT(allocate->HasNoUses());
- allocate->DeleteAndReplaceWith(NULL);
-}
-
-
-void HEscapeAnalysisPhase::PerformScalarReplacement() {
- for (int i = 0; i < captured_.length(); i++) {
- HAllocate* allocate = HAllocate::cast(captured_.at(i));
-
- // Compute number of scalar values and start with clean slate.
- if (!allocate->size()->IsInteger32Constant()) continue;
- int size_in_bytes = allocate->size()->GetInteger32Constant();
- number_of_values_ = size_in_bytes / kPointerSize;
- block_states_.Clear();
-
- // Perform actual analysis steps.
- AnalyzeDataFlow(allocate);
-
- cumulative_values_ += number_of_values_;
- ASSERT(allocate->HasNoUses());
- ASSERT(!allocate->IsLinked());
- }
-}
-
-
} } // namespace v8::internal
diff --git a/chromium/v8/src/hydrogen-escape-analysis.h b/chromium/v8/src/hydrogen-escape-analysis.h
index 123da214e34..6ba6e823c54 100644
--- a/chromium/v8/src/hydrogen-escape-analysis.h
+++ b/chromium/v8/src/hydrogen-escape-analysis.h
@@ -38,48 +38,17 @@ namespace internal {
class HEscapeAnalysisPhase : public HPhase {
public:
explicit HEscapeAnalysisPhase(HGraph* graph)
- : HPhase("H_Escape analysis", graph),
- captured_(0, zone()),
- number_of_values_(0),
- cumulative_values_(0),
- block_states_(graph->blocks()->length(), zone()) { }
+ : HPhase("H_Escape analysis", graph), captured_(0, zone()) { }
void Run() {
CollectCapturedValues();
- PerformScalarReplacement();
}
private:
void CollectCapturedValues();
void CollectIfNoEscapingUses(HInstruction* instr);
- void PerformScalarReplacement();
- void AnalyzeDataFlow(HInstruction* instr);
- HCapturedObject* NewState(HInstruction* prev);
- HCapturedObject* NewStateForAllocation(HInstruction* prev);
- HCapturedObject* NewStateForLoopHeader(HInstruction* prev, HCapturedObject*);
- HCapturedObject* NewStateCopy(HInstruction* prev, HCapturedObject* state);
-
- HPhi* NewPhiAndInsert(HBasicBlock* block, HValue* incoming_value, int index);
-
- HCapturedObject* StateAt(HBasicBlock* block) {
- return block_states_.at(block->block_id());
- }
-
- void SetStateAt(HBasicBlock* block, HCapturedObject* state) {
- block_states_.Set(block->block_id(), state);
- }
-
- // List of allocations captured during collection phase.
- ZoneList<HInstruction*> captured_;
-
- // Number of scalar values tracked during scalar replacement phase.
- int number_of_values_;
- int cumulative_values_;
-
- // Map of block IDs to the data-flow state at block entry during the
- // scalar replacement phase.
- ZoneList<HCapturedObject*> block_states_;
+ ZoneList<HValue*> captured_;
};
diff --git a/chromium/v8/src/hydrogen-instructions.cc b/chromium/v8/src/hydrogen-instructions.cc
index a4c54e761e7..d2f16f46acc 100644
--- a/chromium/v8/src/hydrogen-instructions.cc
+++ b/chromium/v8/src/hydrogen-instructions.cc
@@ -149,6 +149,116 @@ void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) {
}
+// This method is recursive but it is guaranteed to terminate because
+// RedefinedOperand() always dominates "this".
+bool HValue::IsRelationTrue(NumericRelation relation,
+ HValue* other,
+ int offset,
+ int scale) {
+ if (this == other) {
+ return scale == 0 && relation.IsExtendable(offset);
+ }
+
+ // Test the direct relation.
+ if (IsRelationTrueInternal(relation, other, offset, scale)) return true;
+
+ // If scale is 0 try the reversed relation.
+ if (scale == 0 &&
+ // TODO(mmassi): do we need the full, recursive IsRelationTrue?
+ other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) {
+ return true;
+ }
+
+ // Try decomposition (but do not accept scaled compounds).
+ DecompositionResult decomposition;
+ if (TryDecompose(&decomposition) &&
+ decomposition.scale() == 0 &&
+ decomposition.base()->IsRelationTrue(relation, other,
+ offset + decomposition.offset(),
+ scale)) {
+ return true;
+ }
+
+ // Pass the request to the redefined value.
+ HValue* redefined = RedefinedOperand();
+ return redefined != NULL && redefined->IsRelationTrue(relation, other,
+ offset, scale);
+}
+
+
+bool HValue::TryGuaranteeRange(HValue* upper_bound) {
+ RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
+ TryGuaranteeRangeRecursive(&context);
+ bool result = context.is_range_satisfied();
+ if (result) {
+ context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER);
+ context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER);
+ }
+ return result;
+}
+
+
+void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
+ // Check if we already know that this value satisfies the lower bound.
+ if (context->lower_bound_guarantee() == NULL) {
+ if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
+ context->offset(), context->scale())) {
+ context->set_lower_bound_guarantee(this);
+ }
+ }
+
+ // Check if we already know that this value satisfies the upper bound.
+ if (context->upper_bound_guarantee() == NULL) {
+ if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
+ context->offset(), context->scale()) ||
+ (context->scale() == 0 &&
+ context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
+ this, -context->offset()))) {
+ context->set_upper_bound_guarantee(this);
+ }
+ }
+
+ if (context->is_range_satisfied()) return;
+
+ // See if our RedefinedOperand() satisfies the constraints.
+ if (RedefinedOperand() != NULL) {
+ RedefinedOperand()->TryGuaranteeRangeRecursive(context);
+ }
+ if (context->is_range_satisfied()) return;
+
+ // See if the constraints can be satisfied by decomposition.
+ DecompositionResult decomposition;
+ if (TryDecompose(&decomposition)) {
+ context->swap_candidate(&decomposition);
+ context->candidate()->TryGuaranteeRangeRecursive(context);
+ context->swap_candidate(&decomposition);
+ }
+ if (context->is_range_satisfied()) return;
+
+ // Try to modify this to satisfy the constraint.
+
+ TryGuaranteeRangeChanging(context);
+}
+
+
+RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper)
+ : lower_bound_(upper->block()->graph()->GetConstant0()),
+ lower_bound_guarantee_(NULL),
+ candidate_(value),
+ upper_bound_(upper),
+ upper_bound_guarantee_(NULL),
+ offset_(0),
+ scale_(0) {
+}
+
+
+HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
+ return guarantee->IsBoundsCheckBaseIndexInformation()
+ ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
+ : guarantee;
+}
+
+
static int32_t ConvertAndSetOverflow(Representation r,
int64_t result,
bool* overflow) {
@@ -374,6 +484,55 @@ HType HType::TypeFromValue(Handle<Object> value) {
}
+bool HValue::Dominates(HValue* dominator, HValue* dominated) {
+ if (dominator->block() != dominated->block()) {
+ // If they are in different blocks we can use the dominance relation
+ // between the blocks.
+ return dominator->block()->Dominates(dominated->block());
+ } else {
+ // Otherwise we must see which instruction comes first, considering
+ // that phis always precede regular instructions.
+ if (dominator->IsInstruction()) {
+ if (dominated->IsInstruction()) {
+ for (HInstruction* next = HInstruction::cast(dominator)->next();
+ next != NULL;
+ next = next->next()) {
+ if (next == dominated) return true;
+ }
+ return false;
+ } else if (dominated->IsPhi()) {
+ return false;
+ } else {
+ UNREACHABLE();
+ }
+ } else if (dominator->IsPhi()) {
+ if (dominated->IsInstruction()) {
+ return true;
+ } else {
+ // We cannot compare which phi comes first.
+ UNREACHABLE();
+ }
+ } else {
+ UNREACHABLE();
+ }
+ return false;
+ }
+}
+
+
+bool HValue::TestDominanceUsingProcessedFlag(HValue* dominator,
+ HValue* dominated) {
+ if (dominator->block() != dominated->block()) {
+ return dominator->block()->Dominates(dominated->block());
+ } else {
+ // If both arguments are in the same block we check if dominator is a phi
+ // or if dominated has not already been processed: in either case we know
+ // that dominator precedes dominated.
+ return dominator->IsPhi() || !dominated->CheckFlag(kIDefsProcessingDone);
+ }
+}
+
+
bool HValue::IsDefinedAfter(HBasicBlock* other) const {
return block()->block_id() > other->block_id();
}
@@ -388,7 +547,7 @@ HUseListNode* HUseListNode::tail() {
}
-bool HValue::CheckUsesForFlag(Flag f) const {
+bool HValue::CheckUsesForFlag(Flag f) {
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
if (it.value()->IsSimulate()) continue;
if (!it.value()->CheckFlag(f)) return false;
@@ -397,7 +556,7 @@ bool HValue::CheckUsesForFlag(Flag f) const {
}
-bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const {
+bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) {
bool return_value = false;
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
if (it.value()->IsSimulate()) continue;
@@ -801,6 +960,58 @@ void HInstruction::Verify() {
#endif
+HNumericConstraint* HNumericConstraint::AddToGraph(
+ HValue* constrained_value,
+ NumericRelation relation,
+ HValue* related_value,
+ HInstruction* insertion_point) {
+ if (insertion_point == NULL) {
+ if (constrained_value->IsInstruction()) {
+ insertion_point = HInstruction::cast(constrained_value);
+ } else if (constrained_value->IsPhi()) {
+ insertion_point = constrained_value->block()->first();
+ } else {
+ UNREACHABLE();
+ }
+ }
+ HNumericConstraint* result =
+ new(insertion_point->block()->zone()) HNumericConstraint(
+ constrained_value, relation, related_value);
+ result->InsertAfter(insertion_point);
+ return result;
+}
+
+
+void HNumericConstraint::PrintDataTo(StringStream* stream) {
+ stream->Add("(");
+ constrained_value()->PrintNameTo(stream);
+ stream->Add(" %s ", relation().Mnemonic());
+ related_value()->PrintNameTo(stream);
+ stream->Add(")");
+}
+
+
+HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph(
+ HPhi* phi,
+ NumericRelation relation,
+ int operand_index) {
+ HInductionVariableAnnotation* result =
+ new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation,
+ operand_index);
+ result->InsertAfter(phi->block()->first());
+ return result;
+}
+
+
+void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) {
+ stream->Add("(");
+ RedefinedOperand()->PrintNameTo(stream);
+ stream->Add(" %s ", relation().Mnemonic());
+ induction_base()->PrintNameTo(stream);
+ stream->Add(")");
+}
+
+
void HDummyUse::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
}
@@ -827,6 +1038,40 @@ void HBinaryCall::PrintDataTo(StringStream* stream) {
}
+void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
+ if (context->candidate()->ActualValue() != base()->ActualValue() ||
+ context->scale() < scale()) {
+ return;
+ }
+
+ // TODO(mmassi)
+ // Instead of checking for "same basic block" we should check for
+ // "dominates and postdominates".
+ if (context->upper_bound() == length() &&
+ context->lower_bound_guarantee() != NULL &&
+ context->lower_bound_guarantee() != this &&
+ context->lower_bound_guarantee()->block() != block() &&
+ offset() < context->offset() &&
+ index_can_increase() &&
+ context->upper_bound_guarantee() == NULL) {
+ offset_ = context->offset();
+ SetResponsibilityForRange(DIRECTION_UPPER);
+ context->set_upper_bound_guarantee(this);
+ isolate()->counters()->bounds_checks_eliminated()->Increment();
+ } else if (context->upper_bound_guarantee() != NULL &&
+ context->upper_bound_guarantee() != this &&
+ context->upper_bound_guarantee()->block() != block() &&
+ offset() > context->offset() &&
+ index_can_decrease() &&
+ context->lower_bound_guarantee() == NULL) {
+ offset_ = context->offset();
+ SetResponsibilityForRange(DIRECTION_LOWER);
+ context->set_lower_bound_guarantee(this);
+ isolate()->counters()->bounds_checks_eliminated()->Increment();
+ }
+}
+
+
void HBoundsCheck::ApplyIndexChange() {
if (skip_check()) return;
@@ -874,6 +1119,40 @@ void HBoundsCheck::ApplyIndexChange() {
base_ = NULL;
offset_ = 0;
scale_ = 0;
+ responsibility_direction_ = DIRECTION_NONE;
+}
+
+
+void HBoundsCheck::AddInformativeDefinitions() {
+ // TODO(mmassi): Executing this code during AddInformativeDefinitions
+ // is a hack. Move it to some other HPhase.
+ if (FLAG_array_bounds_checks_elimination) {
+ if (index()->TryGuaranteeRange(length())) {
+ set_skip_check();
+ }
+ if (DetectCompoundIndex()) {
+ HBoundsCheckBaseIndexInformation* base_index_info =
+ new(block()->graph()->zone())
+ HBoundsCheckBaseIndexInformation(this);
+ base_index_info->InsertAfter(this);
+ }
+ }
+}
+
+
+bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation,
+ HValue* related_value,
+ int offset,
+ int scale) {
+ if (related_value == length()) {
+ // A HBoundsCheck is smaller than the length it compared against.
+ return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale);
+ } else if (related_value == block()->graph()->GetConstant0()) {
+ // A HBoundsCheck is greater than or equal to zero.
+ return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale);
+ } else {
+ return false;
+ }
}
@@ -916,6 +1195,25 @@ void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) {
}
+bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal(
+ NumericRelation relation,
+ HValue* related_value,
+ int offset,
+ int scale) {
+ if (related_value == bounds_check()->length()) {
+ return NumericRelation::Lt().CompoundImplies(
+ relation,
+ bounds_check()->offset(), bounds_check()->scale(), offset, scale);
+ } else if (related_value == block()->graph()->GetConstant0()) {
+ return NumericRelation::Ge().CompoundImplies(
+ relation,
+ bounds_check()->offset(), bounds_check()->scale(), offset, scale);
+ } else {
+ return false;
+ }
+}
+
+
void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
stream->Add("base: ");
base_index()->PrintNameTo(stream);
@@ -1155,29 +1453,6 @@ void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
}
-static bool MatchLeftIsOnes(HValue* l, HValue* r, HValue** negated) {
- if (!l->EqualsInteger32Constant(~0)) return false;
- *negated = r;
- return true;
-}
-
-
-static bool MatchNegationViaXor(HValue* instr, HValue** negated) {
- if (!instr->IsBitwise()) return false;
- HBitwise* b = HBitwise::cast(instr);
- return (b->op() == Token::BIT_XOR) &&
- (MatchLeftIsOnes(b->left(), b->right(), negated) ||
- MatchLeftIsOnes(b->right(), b->left(), negated));
-}
-
-
-static bool MatchDoubleNegation(HValue* instr, HValue** arg) {
- HValue* negated;
- return MatchNegationViaXor(instr, &negated) &&
- MatchNegationViaXor(negated, arg);
-}
-
-
HValue* HBitwise::Canonicalize() {
if (!representation().IsSmiOrInteger32()) return this;
// If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
@@ -1190,10 +1465,18 @@ HValue* HBitwise::Canonicalize() {
!left()->CheckFlag(kUint32)) {
return left();
}
- // Optimize double negation, a common pattern used for ToInt32(x).
- HValue* arg;
- if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) {
- return arg;
+ return this;
+}
+
+
+HValue* HBitNot::Canonicalize() {
+ // Optimize ~~x, a common pattern used for ToInt32(x).
+ if (value()->IsBitNot()) {
+ HValue* result = HBitNot::cast(value())->value();
+ ASSERT(result->representation().IsInteger32());
+ if (!result->CheckFlag(kUint32)) {
+ return result;
+ }
}
return this;
}
@@ -1285,16 +1568,16 @@ static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
HValue* HUnaryMathOperation::Canonicalize() {
- if (op() == kMathRound || op() == kMathFloor) {
+ if (op() == kMathRound) {
HValue* val = value();
if (val->IsChange()) val = HChange::cast(val)->value();
- // If the input is smi or integer32 then we replace the instruction with its
- // input.
+ // If the input is integer32 then we replace the round instruction
+ // with its input.
if (val->representation().IsSmiOrInteger32()) {
if (!val->representation().Equals(representation())) {
HChange* result = new(block()->zone()) HChange(
- val, representation(), false, false);
+ val, representation(), false, false, false);
result->InsertBefore(this);
return result;
}
@@ -1305,6 +1588,19 @@ HValue* HUnaryMathOperation::Canonicalize() {
if (op() == kMathFloor) {
HValue* val = value();
if (val->IsChange()) val = HChange::cast(val)->value();
+
+ // If the input is integer32 then we replace the floor instruction
+ // with its input.
+ if (val->representation().IsSmiOrInteger32()) {
+ if (!val->representation().Equals(representation())) {
+ HChange* result = new(block()->zone()) HChange(
+ val, representation(), false, false, false);
+ result->InsertBefore(this);
+ return result;
+ }
+ return val;
+ }
+
if (val->IsDiv() && (val->UseCount() == 1)) {
HDiv* hdiv = HDiv::cast(val);
HValue* left = hdiv->left();
@@ -1314,7 +1610,7 @@ HValue* HUnaryMathOperation::Canonicalize() {
if (new_left == NULL &&
hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
new_left = new(block()->zone()) HChange(
- left, Representation::Integer32(), false, false);
+ left, Representation::Integer32(), false, false, false);
HChange::cast(new_left)->InsertBefore(this);
}
HValue* new_right =
@@ -1325,7 +1621,7 @@ HValue* HUnaryMathOperation::Canonicalize() {
#endif
hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
new_right = new(block()->zone()) HChange(
- right, Representation::Integer32(), false, false);
+ right, Representation::Integer32(), false, false, false);
HChange::cast(new_right)->InsertBefore(this);
}
@@ -1416,10 +1712,10 @@ void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
// for which the map is known.
if (HasNoUses() && dominator->IsStoreNamedField()) {
HStoreNamedField* store = HStoreNamedField::cast(dominator);
- if (!store->has_transition() || store->object() != value()) return;
- HConstant* transition = HConstant::cast(store->transition());
+ UniqueValueId map_unique_id = store->transition_unique_id();
+ if (!map_unique_id.IsInitialized() || store->object() != value()) return;
for (int i = 0; i < map_set()->length(); i++) {
- if (transition->UniqueValueIdsMatch(map_unique_ids_.at(i))) {
+ if (map_unique_id == map_unique_ids_.at(i)) {
DeleteAndReplaceWith(NULL);
return;
}
@@ -1470,6 +1766,13 @@ void HCheckInstanceType::PrintDataTo(StringStream* stream) {
}
+void HCheckPrototypeMaps::PrintDataTo(StringStream* stream) {
+ stream->Add("[receiver_prototype=%p,holder=%p]%s",
+ *prototypes_.first(), *prototypes_.last(),
+ CanOmitPrototypeChecks() ? " (omitted)" : "");
+}
+
+
void HCallStub::PrintDataTo(StringStream* stream) {
stream->Add("%s ",
CodeStub::MajorName(major_key_, false));
@@ -1672,6 +1975,60 @@ Range* HMod::InferRange(Zone* zone) {
}
+void HPhi::AddInformativeDefinitions() {
+ if (OperandCount() == 2) {
+ // If one of the operands is an OSR block give up (this cannot be an
+ // induction variable).
+ if (OperandAt(0)->block()->is_osr_entry() ||
+ OperandAt(1)->block()->is_osr_entry()) return;
+
+ for (int operand_index = 0; operand_index < 2; operand_index++) {
+ int other_operand_index = (operand_index + 1) % 2;
+
+ static NumericRelation relations[] = {
+ NumericRelation::Ge(),
+ NumericRelation::Le()
+ };
+
+ // Check if this phi is an induction variable. If, e.g., we know that
+ // its first input is greater than the phi itself, then that must be
+ // the back edge, and the phi is always greater than its second input.
+ for (int relation_index = 0; relation_index < 2; relation_index++) {
+ if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index],
+ this)) {
+ HInductionVariableAnnotation::AddToGraph(this,
+ relations[relation_index],
+ other_operand_index);
+ }
+ }
+ }
+ }
+}
+
+
+bool HPhi::IsRelationTrueInternal(NumericRelation relation,
+ HValue* other,
+ int offset,
+ int scale) {
+ if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
+
+ SetFlag(kNumericConstraintEvaluationInProgress);
+ bool result = true;
+ for (int i = 0; i < OperandCount(); i++) {
+ // Skip OSR entry blocks
+ if (OperandAt(i)->block()->is_osr_entry()) continue;
+
+ if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) {
+ result = false;
+ break;
+ }
+ }
+ ClearFlag(kNumericConstraintEvaluationInProgress);
+
+ return result;
+}
+
+
InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) {
if (phi->block()->loop_information() == NULL) return NULL;
if (phi->OperandCount() != 2) return NULL;
@@ -2423,14 +2780,6 @@ HConstant::HConstant(ExternalReference reference)
}
-static void PrepareConstant(Handle<Object> object) {
- if (!object->IsJSObject()) return;
- Handle<JSObject> js_object = Handle<JSObject>::cast(object);
- if (!js_object->map()->is_deprecated()) return;
- JSObject::TryMigrateInstance(js_object);
-}
-
-
void HConstant::Initialize(Representation r) {
if (r.IsNone()) {
if (has_smi_value_ && kSmiValueSize == 31) {
@@ -2442,7 +2791,6 @@ void HConstant::Initialize(Representation r) {
} else if (has_external_reference_value_) {
r = Representation::External();
} else {
- PrepareConstant(handle_);
r = Representation::Tagged();
}
}
@@ -2767,6 +3115,16 @@ void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
}
+void HCompareNumericAndBranch::AddInformativeDefinitions() {
+ NumericRelation r = NumericRelation::FromToken(token());
+ if (r.IsNone()) return;
+
+ HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first());
+ HNumericConstraint::AddToGraph(
+ left(), r.Negated(), right(), SuccessorAt(1)->first());
+}
+
+
void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
stream->Add(Token::Name(token()));
stream->Add(" ");
@@ -2785,18 +3143,6 @@ void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
}
-void HCompareHoleAndBranch::PrintDataTo(StringStream* stream) {
- object()->PrintNameTo(stream);
- HControlInstruction::PrintDataTo(stream);
-}
-
-
-void HCompareHoleAndBranch::InferRepresentation(
- HInferRepresentationPhase* h_infer) {
- ChangeRepresentation(object()->representation());
-}
-
-
void HGoto::PrintDataTo(StringStream* stream) {
stream->Add("B%d", SuccessorAt(0)->block_id());
}
@@ -2856,6 +3202,119 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
}
+// Returns true if an instance of this map can never find a property with this
+// name in its prototype chain. This means all prototypes up to the top are
+// fast and don't have the name in them. It would be good if we could optimize
+// polymorphic loads where the property is sometimes found in the prototype
+// chain.
+static bool PrototypeChainCanNeverResolve(
+ Handle<Map> map, Handle<String> name) {
+ Isolate* isolate = map->GetIsolate();
+ Object* current = map->prototype();
+ while (current != isolate->heap()->null_value()) {
+ if (current->IsJSGlobalProxy() ||
+ current->IsGlobalObject() ||
+ !current->IsJSObject() ||
+ JSObject::cast(current)->map()->has_named_interceptor() ||
+ JSObject::cast(current)->IsAccessCheckNeeded() ||
+ !JSObject::cast(current)->HasFastProperties()) {
+ return false;
+ }
+
+ LookupResult lookup(isolate);
+ Map* map = JSObject::cast(current)->map();
+ map->LookupDescriptor(NULL, *name, &lookup);
+ if (lookup.IsFound()) return false;
+ if (!lookup.IsCacheable()) return false;
+ current = JSObject::cast(current)->GetPrototype();
+ }
+ return true;
+}
+
+
+HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
+ HValue* object,
+ SmallMapList* types,
+ Handle<String> name,
+ Zone* zone)
+ : types_(Min(types->length(), kMaxLoadPolymorphism), zone),
+ name_(name),
+ types_unique_ids_(0, zone),
+ name_unique_id_(),
+ need_generic_(false) {
+ SetOperandAt(0, context);
+ SetOperandAt(1, object);
+ set_representation(Representation::Tagged());
+ SetGVNFlag(kDependsOnMaps);
+ SmallMapList negative_lookups;
+ for (int i = 0;
+ i < types->length() && types_.length() < kMaxLoadPolymorphism;
+ ++i) {
+ Handle<Map> map = types->at(i);
+ // Deprecated maps are updated to the current map in the type oracle.
+ ASSERT(!map->is_deprecated());
+ LookupResult lookup(map->GetIsolate());
+ map->LookupDescriptor(NULL, *name, &lookup);
+ if (lookup.IsFound()) {
+ switch (lookup.type()) {
+ case FIELD: {
+ int index = lookup.GetLocalFieldIndexFromMap(*map);
+ if (index < 0) {
+ SetGVNFlag(kDependsOnInobjectFields);
+ } else {
+ SetGVNFlag(kDependsOnBackingStoreFields);
+ }
+ if (FLAG_track_double_fields &&
+ lookup.representation().IsDouble()) {
+ // Since the value needs to be boxed, use a generic handler for
+ // loading doubles.
+ continue;
+ }
+ types_.Add(types->at(i), zone);
+ break;
+ }
+ case CONSTANT:
+ types_.Add(types->at(i), zone);
+ break;
+ case CALLBACKS:
+ break;
+ case TRANSITION:
+ case INTERCEPTOR:
+ case NONEXISTENT:
+ case NORMAL:
+ case HANDLER:
+ UNREACHABLE();
+ break;
+ }
+ } else if (lookup.IsCacheable() &&
+ // For dicts the lookup on the map will fail, but the object may
+ // contain the property so we cannot generate a negative lookup
+ // (which would just be a map check and return undefined).
+ !map->is_dictionary_map() &&
+ !map->has_named_interceptor() &&
+ PrototypeChainCanNeverResolve(map, name)) {
+ negative_lookups.Add(types->at(i), zone);
+ }
+ }
+
+ bool need_generic =
+ (types->length() != negative_lookups.length() + types_.length());
+ if (!need_generic && FLAG_deoptimize_uncommon_cases) {
+ SetFlag(kUseGVN);
+ for (int i = 0; i < negative_lookups.length(); i++) {
+ types_.Add(negative_lookups.at(i), zone);
+ }
+ } else {
+ // We don't have an easy way to handle both a call (to the generic stub) and
+ // a deopt in the same hydrogen instruction, so in this case we don't add
+ // the negative lookups which can deopt - just let the generic stub handle
+ // them.
+ SetAllSideEffects();
+ need_generic_ = true;
+ }
+}
+
+
HCheckMaps* HCheckMaps::New(Zone* zone,
HValue* context,
HValue* value,
@@ -2863,7 +3322,7 @@ HCheckMaps* HCheckMaps::New(Zone* zone,
CompilationInfo* info,
HValue* typecheck) {
HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
- check_map->Add(map, zone);
+ check_map->map_set_.Add(map, zone);
if (map->CanOmitMapChecks() &&
value->IsConstant() &&
HConstant::cast(value)->InstanceOf(map)) {
@@ -2883,6 +3342,46 @@ void HCheckMaps::FinalizeUniqueValueId() {
}
+void HLoadNamedFieldPolymorphic::FinalizeUniqueValueId() {
+ if (!types_unique_ids_.is_empty()) return;
+ Zone* zone = block()->zone();
+ types_unique_ids_.Initialize(types_.length(), zone);
+ for (int i = 0; i < types_.length(); i++) {
+ types_unique_ids_.Add(UniqueValueId(types_.at(i)), zone);
+ }
+ name_unique_id_ = UniqueValueId(name_);
+}
+
+
+bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
+ ASSERT_EQ(types_.length(), types_unique_ids_.length());
+ HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
+ if (name_unique_id_ != other->name_unique_id_) return false;
+ if (types_unique_ids_.length() != other->types_unique_ids_.length()) {
+ return false;
+ }
+ if (need_generic_ != other->need_generic_) return false;
+ for (int i = 0; i < types_unique_ids_.length(); i++) {
+ bool found = false;
+ for (int j = 0; j < types_unique_ids_.length(); j++) {
+ if (types_unique_ids_.at(j) == other->types_unique_ids_.at(i)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) return false;
+ }
+ return true;
+}
+
+
+void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
+ object()->PrintNameTo(stream);
+ stream->Add(".");
+ stream->Add(*String::cast(*name())->ToCString());
+}
+
+
void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(".");
@@ -2955,8 +3454,18 @@ bool HLoadKeyed::UsesMustHandleHole() const {
bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const {
- return IsFastDoubleElementsKind(elements_kind()) &&
- CheckUsesForFlag(HValue::kAllowUndefinedAsNaN);
+ if (!IsFastDoubleElementsKind(elements_kind())) {
+ return false;
+ }
+
+ for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ HValue* use = it.value();
+ if (!use->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
+ return false;
+ }
+ }
+
+ return true;
}
@@ -3038,8 +3547,8 @@ void HStoreNamedField::PrintDataTo(StringStream* stream) {
if (NeedsWriteBarrier()) {
stream->Add(" (write-barrier)");
}
- if (has_transition()) {
- stream->Add(" (transition map %p)", *transition_map());
+ if (!transition().is_null()) {
+ stream->Add(" (transition map %p)", *transition());
}
}
@@ -3175,6 +3684,8 @@ Representation HUnaryMathOperation::RepresentationFromInputs() {
Representation input_rep = value()->representation();
if (!input_rep.IsTagged()) {
rep = rep.generalize(input_rep);
+ } else if (flexible_int()) {
+ rep = Representation::Integer32();
}
return rep;
}
@@ -3731,10 +4242,10 @@ void HPhi::SimplifyConstantInputs() {
DoubleToInt32(operand->DoubleValue()));
integer_input->InsertAfter(operand);
SetOperandAt(i, integer_input);
- } else if (operand->HasBooleanValue()) {
- SetOperandAt(i, operand->BooleanValue() ? graph->GetConstant1()
- : graph->GetConstant0());
- } else if (operand->ImmortalImmovable()) {
+ } else if (operand == graph->GetConstantTrue()) {
+ SetOperandAt(i, graph->GetConstant1());
+ } else {
+ // This catches |false|, |undefined|, strings and objects.
SetOperandAt(i, graph->GetConstant0());
}
}
diff --git a/chromium/v8/src/hydrogen-instructions.h b/chromium/v8/src/hydrogen-instructions.h
index 41f9d0d5ccd..78e9a6b192a 100644
--- a/chromium/v8/src/hydrogen-instructions.h
+++ b/chromium/v8/src/hydrogen-instructions.h
@@ -72,6 +72,7 @@ class LChunkBuilder;
V(ArgumentsLength) \
V(ArgumentsObject) \
V(Bitwise) \
+ V(BitNot) \
V(BlockEntry) \
V(BoundsCheck) \
V(BoundsCheckBaseIndexInformation) \
@@ -86,18 +87,17 @@ class LChunkBuilder;
V(CallNewArray) \
V(CallRuntime) \
V(CallStub) \
- V(CapturedObject) \
V(Change) \
V(CheckFunction) \
V(CheckHeapObject) \
V(CheckInstanceType) \
V(CheckMaps) \
V(CheckMapValue) \
+ V(CheckPrototypeMaps) \
V(CheckSmi) \
V(ClampToUint8) \
V(ClassOfTestAndBranch) \
V(CompareNumericAndBranch) \
- V(CompareHoleAndBranch) \
V(CompareGeneric) \
V(CompareObjectEqAndBranch) \
V(CompareMap) \
@@ -122,6 +122,7 @@ class LChunkBuilder;
V(Goto) \
V(HasCachedArrayIndexAndBranch) \
V(HasInstanceTypeAndBranch) \
+ V(InductionVariableAnnotation) \
V(InnerAllocatedObject) \
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
@@ -143,12 +144,14 @@ class LChunkBuilder;
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
+ V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathFloorOfDiv) \
V(MathMinMax) \
V(Mod) \
V(Mul) \
+ V(NumericConstraint) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
@@ -539,6 +542,158 @@ enum GVNFlag {
};
+class NumericRelation {
+ public:
+ enum Kind { NONE, EQ, GT, GE, LT, LE, NE };
+ static const char* MnemonicFromKind(Kind kind) {
+ switch (kind) {
+ case NONE: return "NONE";
+ case EQ: return "EQ";
+ case GT: return "GT";
+ case GE: return "GE";
+ case LT: return "LT";
+ case LE: return "LE";
+ case NE: return "NE";
+ }
+ UNREACHABLE();
+ return NULL;
+ }
+ const char* Mnemonic() const { return MnemonicFromKind(kind_); }
+
+ static NumericRelation None() { return NumericRelation(NONE); }
+ static NumericRelation Eq() { return NumericRelation(EQ); }
+ static NumericRelation Gt() { return NumericRelation(GT); }
+ static NumericRelation Ge() { return NumericRelation(GE); }
+ static NumericRelation Lt() { return NumericRelation(LT); }
+ static NumericRelation Le() { return NumericRelation(LE); }
+ static NumericRelation Ne() { return NumericRelation(NE); }
+
+ bool IsNone() { return kind_ == NONE; }
+
+ static NumericRelation FromToken(Token::Value token) {
+ switch (token) {
+ case Token::EQ: return Eq();
+ case Token::EQ_STRICT: return Eq();
+ case Token::LT: return Lt();
+ case Token::GT: return Gt();
+ case Token::LTE: return Le();
+ case Token::GTE: return Ge();
+ case Token::NE: return Ne();
+ case Token::NE_STRICT: return Ne();
+ default: return None();
+ }
+ }
+
+ // The semantics of "Reversed" is that if "x rel y" is true then also
+ // "y rel.Reversed() x" is true, and that rel.Reversed().Reversed() == rel.
+ NumericRelation Reversed() {
+ switch (kind_) {
+ case NONE: return None();
+ case EQ: return Eq();
+ case GT: return Lt();
+ case GE: return Le();
+ case LT: return Gt();
+ case LE: return Ge();
+ case NE: return Ne();
+ }
+ UNREACHABLE();
+ return None();
+ }
+
+ // The semantics of "Negated" is that if "x rel y" is true then also
+ // "!(x rel.Negated() y)" is true.
+ NumericRelation Negated() {
+ switch (kind_) {
+ case NONE: return None();
+ case EQ: return Ne();
+ case GT: return Le();
+ case GE: return Lt();
+ case LT: return Ge();
+ case LE: return Gt();
+ case NE: return Eq();
+ }
+ UNREACHABLE();
+ return None();
+ }
+
+ // The semantics of "Implies" is that if "x rel y" is true
+ // then also "x other_relation y" is true.
+ bool Implies(NumericRelation other_relation) {
+ switch (kind_) {
+ case NONE: return false;
+ case EQ: return (other_relation.kind_ == EQ)
+ || (other_relation.kind_ == GE)
+ || (other_relation.kind_ == LE);
+ case GT: return (other_relation.kind_ == GT)
+ || (other_relation.kind_ == GE)
+ || (other_relation.kind_ == NE);
+ case LT: return (other_relation.kind_ == LT)
+ || (other_relation.kind_ == LE)
+ || (other_relation.kind_ == NE);
+ case GE: return (other_relation.kind_ == GE);
+ case LE: return (other_relation.kind_ == LE);
+ case NE: return (other_relation.kind_ == NE);
+ }
+ UNREACHABLE();
+ return false;
+ }
+
+ // The semantics of "IsExtendable" is that if
+ // "rel.IsExtendable(direction)" is true then
+ // "x rel y" implies "(x + direction) rel y" .
+ bool IsExtendable(int direction) {
+ switch (kind_) {
+ case NONE: return false;
+ case EQ: return false;
+ case GT: return (direction >= 0);
+ case GE: return (direction >= 0);
+ case LT: return (direction <= 0);
+ case LE: return (direction <= 0);
+ case NE: return false;
+ }
+ UNREACHABLE();
+ return false;
+ }
+
+ // CompoundImplies returns true when
+ // "((x + my_offset) >> my_scale) rel y" implies
+ // "((x + other_offset) >> other_scale) other_relation y".
+ bool CompoundImplies(NumericRelation other_relation,
+ int my_offset,
+ int my_scale,
+ int other_offset = 0,
+ int other_scale = 0) {
+ return Implies(other_relation) && ComponentsImply(
+ my_offset, my_scale, other_offset, other_scale);
+ }
+
+ private:
+ // ComponentsImply returns true when
+ // "((x + my_offset) >> my_scale) rel y" implies
+ // "((x + other_offset) >> other_scale) rel y".
+ bool ComponentsImply(int my_offset,
+ int my_scale,
+ int other_offset,
+ int other_scale) {
+ switch (kind_) {
+ case NONE: break; // Fall through to UNREACHABLE().
+ case EQ:
+ case NE: return my_offset == other_offset && my_scale == other_scale;
+ case GT:
+ case GE: return my_offset <= other_offset && my_scale >= other_scale;
+ case LT:
+ case LE: return my_offset >= other_offset && my_scale <= other_scale;
+ }
+ UNREACHABLE();
+ return false;
+ }
+
+ explicit NumericRelation(Kind kind) : kind_(kind) {}
+
+ Kind kind_;
+};
+
+
class DecompositionResult BASE_EMBEDDED {
public:
DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
@@ -584,6 +739,46 @@ class DecompositionResult BASE_EMBEDDED {
};
+class RangeEvaluationContext BASE_EMBEDDED {
+ public:
+ RangeEvaluationContext(HValue* value, HValue* upper);
+
+ HValue* lower_bound() { return lower_bound_; }
+ HValue* lower_bound_guarantee() { return lower_bound_guarantee_; }
+ HValue* candidate() { return candidate_; }
+ HValue* upper_bound() { return upper_bound_; }
+ HValue* upper_bound_guarantee() { return upper_bound_guarantee_; }
+ int offset() { return offset_; }
+ int scale() { return scale_; }
+
+ bool is_range_satisfied() {
+ return lower_bound_guarantee() != NULL && upper_bound_guarantee() != NULL;
+ }
+
+ void set_lower_bound_guarantee(HValue* guarantee) {
+ lower_bound_guarantee_ = ConvertGuarantee(guarantee);
+ }
+ void set_upper_bound_guarantee(HValue* guarantee) {
+ upper_bound_guarantee_ = ConvertGuarantee(guarantee);
+ }
+
+ void swap_candidate(DecompositionResult* other_candicate) {
+ other_candicate->SwapValues(&candidate_, &offset_, &scale_);
+ }
+
+ private:
+ HValue* ConvertGuarantee(HValue* guarantee);
+
+ HValue* lower_bound_;
+ HValue* lower_bound_guarantee_;
+ HValue* candidate_;
+ HValue* upper_bound_;
+ HValue* upper_bound_guarantee_;
+ int offset_;
+ int scale_;
+};
+
+
typedef EnumSet<GVNFlag> GVNFlagSet;
@@ -621,6 +816,12 @@ class HValue: public ZoneObject {
// HGraph::ComputeSafeUint32Operations is responsible for setting this
// flag.
kUint32,
+ // If a phi is involved in the evaluation of a numeric constraint the
+ // recursion can cause an endless cycle: we use this flag to exit the loop.
+ kNumericConstraintEvaluationInProgress,
+ // This flag is set to true after the SetupInformativeDefinitions() pass
+ // has processed this instruction.
+ kIDefsProcessingDone,
kHasNoObservableSideEffects,
// Indicates the instruction is live during dead code elimination.
kIsLive,
@@ -758,8 +959,8 @@ class HValue: public ZoneObject {
return RedefinedOperandIndex() != kNoRedefinedOperand;
}
HValue* RedefinedOperand() {
- int index = RedefinedOperandIndex();
- return index == kNoRedefinedOperand ? NULL : OperandAt(index);
+ return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
+ : NULL;
}
// A purely informative definition is an idef that will not emit code and
@@ -770,8 +971,17 @@ class HValue: public ZoneObject {
// This method must always return the original HValue SSA definition
// (regardless of any iDef of this value).
HValue* ActualValue() {
- int index = RedefinedOperandIndex();
- return index == kNoRedefinedOperand ? this : OperandAt(index);
+ return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
+ : this;
+ }
+
+ virtual void AddInformativeDefinitions() {}
+
+ void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
+ UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
+ }
+ void UpdateRedefinedUses() {
+ UpdateRedefinedUsesInner<Dominates>();
}
bool IsInteger32Constant();
@@ -802,10 +1012,10 @@ class HValue: public ZoneObject {
bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
// Returns true if the flag specified is set for all uses, false otherwise.
- bool CheckUsesForFlag(Flag f) const;
+ bool CheckUsesForFlag(Flag f);
// Returns true if the flag specified is set for all uses, and this set
// of uses is non-empty.
- bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
+ bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f);
GVNFlagSet gvn_flags() const { return gvn_flags_; }
void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
@@ -922,6 +1132,12 @@ class HValue: public ZoneObject {
virtual void Verify() = 0;
#endif
+ bool IsRelationTrue(NumericRelation relation,
+ HValue* other,
+ int offset = 0,
+ int scale = 0);
+
+ bool TryGuaranteeRange(HValue* upper_bound);
virtual bool TryDecompose(DecompositionResult* decomposition) {
if (RedefinedOperand() != NULL) {
return RedefinedOperand()->TryDecompose(decomposition);
@@ -943,6 +1159,17 @@ class HValue: public ZoneObject {
}
protected:
+ void TryGuaranteeRangeRecursive(RangeEvaluationContext* context);
+
+ enum RangeGuaranteeDirection {
+ DIRECTION_NONE = 0,
+ DIRECTION_UPPER = 1,
+ DIRECTION_LOWER = 2,
+ DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER
+ };
+ virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {}
+ virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {}
+
// This function must be overridden for instructions with flag kUseGVN, to
// compare the non-Operand parts of the instruction.
virtual bool DataEquals(HValue* other) {
@@ -976,6 +1203,47 @@ class HValue: public ZoneObject {
representation_ = r;
}
+ // Signature of a function testing if a HValue properly dominates another.
+ typedef bool (*DominanceTest)(HValue*, HValue*);
+
+ // Simple implementation of DominanceTest implemented walking the chain
+ // of Hinstructions (used in UpdateRedefinedUsesInner).
+ static bool Dominates(HValue* dominator, HValue* dominated);
+
+ // A fast implementation of DominanceTest that works only for the
+ // "current" instruction in the SetupInformativeDefinitions() phase.
+ // During that phase we use a flag to mark processed instructions, and by
+ // checking the flag we can quickly test if an instruction comes before or
+ // after the "current" one.
+ static bool TestDominanceUsingProcessedFlag(HValue* dominator,
+ HValue* dominated);
+
+ // If we are redefining an operand, update all its dominated uses (the
+ // function that checks if a use is dominated is the template argument).
+ template<DominanceTest TestDominance>
+ void UpdateRedefinedUsesInner() {
+ HValue* input = RedefinedOperand();
+ if (input != NULL) {
+ for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) {
+ HValue* use = uses.value();
+ if (TestDominance(this, use)) {
+ use->SetOperandAt(uses.index(), this);
+ }
+ }
+ }
+ }
+
+ // Informative definitions can override this method to state any numeric
+ // relation they provide on the redefined value.
+ // Returns true if it is guaranteed that:
+ // ((this + offset) >> scale) relation other
+ virtual bool IsRelationTrueInternal(NumericRelation relation,
+ HValue* other,
+ int offset = 0,
+ int scale = 0) {
+ return false;
+ }
+
static GVNFlagSet AllDependsOnFlagSet() {
GVNFlagSet result;
// Create changes mask.
@@ -1246,25 +1514,67 @@ class HDummyUse: public HTemplateInstruction<1> {
};
+class HNumericConstraint : public HTemplateInstruction<2> {
+ public:
+ static HNumericConstraint* AddToGraph(HValue* constrained_value,
+ NumericRelation relation,
+ HValue* related_value,
+ HInstruction* insertion_point = NULL);
+
+ HValue* constrained_value() { return OperandAt(0); }
+ HValue* related_value() { return OperandAt(1); }
+ NumericRelation relation() { return relation_; }
+
+ virtual int RedefinedOperandIndex() { return 0; }
+ virtual bool IsPurelyInformativeDefinition() { return true; }
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return representation();
+ }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ virtual bool IsRelationTrueInternal(NumericRelation other_relation,
+ HValue* other_related_value,
+ int offset = 0,
+ int scale = 0) {
+ if (related_value() == other_related_value) {
+ return relation().CompoundImplies(other_relation, offset, scale);
+ } else {
+ return false;
+ }
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(NumericConstraint)
+
+ private:
+ HNumericConstraint(HValue* constrained_value,
+ NumericRelation relation,
+ HValue* related_value)
+ : relation_(relation) {
+ SetOperandAt(0, constrained_value);
+ SetOperandAt(1, related_value);
+ }
+
+ NumericRelation relation_;
+};
+
+
class HDeoptimize: public HTemplateInstruction<0> {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HDeoptimize, const char*,
- Deoptimizer::BailoutType);
+ DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType);
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
- const char* reason() const { return reason_; }
Deoptimizer::BailoutType type() { return type_; }
DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
private:
- explicit HDeoptimize(const char* reason, Deoptimizer::BailoutType type)
- : reason_(reason), type_(type) {}
+ explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
- const char* reason_;
Deoptimizer::BailoutType type_;
};
@@ -1522,13 +1832,15 @@ class HChange: public HUnaryOperation {
HChange(HValue* value,
Representation to,
bool is_truncating_to_smi,
- bool is_truncating_to_int32)
+ bool is_truncating_to_int32,
+ bool allow_undefined_as_nan)
: HUnaryOperation(value) {
ASSERT(!value->representation().IsNone());
ASSERT(!to.IsNone());
ASSERT(!value->representation().Equals(to));
set_representation(to);
SetFlag(kUseGVN);
+ if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN);
if (is_truncating_to_smi) SetFlag(kTruncatingToSmi);
if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
if (value->representation().IsSmi() || value->type().IsSmi()) {
@@ -1539,16 +1851,15 @@ class HChange: public HUnaryOperation {
}
}
- bool can_convert_undefined_to_nan() {
- return CheckUsesForFlag(kAllowUndefinedAsNaN);
- }
-
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
virtual HType CalculateInferredType();
virtual HValue* Canonicalize();
Representation from() const { return value()->representation(); }
Representation to() const { return representation(); }
+ bool allow_undefined_as_nan() const {
+ return CheckFlag(kAllowUndefinedAsNaN);
+ }
bool deoptimize_on_minus_zero() const {
return CheckFlag(kBailoutOnMinusZero);
}
@@ -2395,6 +2706,37 @@ class HElementsKind: public HUnaryOperation {
};
+class HBitNot: public HUnaryOperation {
+ public:
+ DECLARE_INSTRUCTION_FACTORY_P1(HBitNot, HValue*);
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::Integer32();
+ }
+ virtual Representation observed_input_representation(int index) {
+ return Representation::Integer32();
+ }
+
+ virtual HValue* Canonicalize();
+
+ DECLARE_CONCRETE_INSTRUCTION(BitNot)
+
+ protected:
+ virtual bool DataEquals(HValue* other) { return true; }
+
+ private:
+ explicit HBitNot(HValue* value)
+ : HUnaryOperation(value, HType::TaggedNumber()) {
+ set_representation(Representation::Integer32());
+ SetFlag(kUseGVN);
+ SetFlag(kTruncatingToInt32);
+ SetFlag(kAllowUndefinedAsNaN);
+ }
+
+ virtual bool IsDeletable() const { return true; }
+};
+
+
class HUnaryMathOperation: public HTemplateInstruction<2> {
public:
static HInstruction* New(Zone* zone,
@@ -2433,6 +2775,21 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
}
}
+ virtual void UpdateRepresentation(Representation new_rep,
+ HInferRepresentationPhase* h_infer,
+ const char* reason) {
+ if (flexible_int() && !new_rep.IsSmi()) {
+ new_rep = Representation::Integer32();
+ }
+ HValue::UpdateRepresentation(new_rep, h_infer, reason);
+ }
+
+ virtual void RepresentationChanged(Representation new_rep) {
+ if (flexible_int() && new_rep.IsInteger32()) {
+ ClearFlag(kFlexibleRepresentation);
+ }
+ }
+
virtual Range* InferRange(Zone* zone);
virtual HValue* Canonicalize();
@@ -2450,6 +2807,10 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
}
private:
+ bool flexible_int() {
+ return op_ == kMathFloor || op_ == kMathRound;
+ }
+
HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
: HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
SetOperandAt(0, context);
@@ -2457,7 +2818,8 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
switch (op) {
case kMathFloor:
case kMathRound:
- set_representation(Representation::Integer32());
+ set_representation(Representation::Smi());
+ SetFlag(kFlexibleRepresentation);
break;
case kMathAbs:
// Not setting representation here: it is None intentionally.
@@ -2534,7 +2896,7 @@ class HCheckMaps: public HTemplateInstruction<2> {
HValue *typecheck = NULL) {
HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
for (int i = 0; i < maps->length(); i++) {
- check_map->Add(maps->at(i), zone);
+ check_map->map_set_.Add(maps->at(i), zone);
}
check_map->map_set_.Sort();
return check_map;
@@ -2553,10 +2915,6 @@ class HCheckMaps: public HTemplateInstruction<2> {
HValue* value() { return OperandAt(0); }
SmallMapList* map_set() { return &map_set_; }
- bool has_migration_target() {
- return has_migration_target_;
- }
-
virtual void FinalizeUniqueValueId();
DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
@@ -2578,18 +2936,10 @@ class HCheckMaps: public HTemplateInstruction<2> {
}
private:
- void Add(Handle<Map> map, Zone* zone) {
- map_set_.Add(map, zone);
- if (!has_migration_target_ && map->is_migration_target()) {
- has_migration_target_ = true;
- SetGVNFlag(kChangesNewSpacePromotion);
- }
- }
-
// Clients should use one of the static New* methods above.
HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
: HTemplateInstruction<2>(value->type()),
- omit_(false), has_migration_target_(false), map_unique_ids_(0, zone) {
+ omit_(false), map_unique_ids_(0, zone) {
SetOperandAt(0, value);
// Use the object value for the dependency if NULL is passed.
// TODO(titzer): do GVN flags already express this dependency?
@@ -2611,7 +2961,6 @@ class HCheckMaps: public HTemplateInstruction<2> {
}
bool omit_;
- bool has_migration_target_;
SmallMapList map_set_;
ZoneList<UniqueValueId> map_unique_ids_;
};
@@ -2770,7 +3119,6 @@ class HCheckHeapObject: public HUnaryOperation {
public:
DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
- virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
}
@@ -2797,6 +3145,87 @@ class HCheckHeapObject: public HUnaryOperation {
};
+class HCheckPrototypeMaps: public HTemplateInstruction<0> {
+ public:
+ static HCheckPrototypeMaps* New(Zone* zone,
+ HValue* context,
+ Handle<JSObject> prototype,
+ Handle<JSObject> holder,
+ CompilationInfo* info) {
+ return new(zone) HCheckPrototypeMaps(prototype, holder, zone, info);
+ }
+
+ ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
+
+ ZoneList<Handle<Map> >* maps() { return &maps_; }
+
+ DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::None();
+ }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ virtual intptr_t Hashcode() {
+ return first_prototype_unique_id_.Hashcode() * 17 +
+ last_prototype_unique_id_.Hashcode();
+ }
+
+ virtual void FinalizeUniqueValueId() {
+ first_prototype_unique_id_ = UniqueValueId(prototypes_.first());
+ last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
+ }
+
+ bool CanOmitPrototypeChecks() { return can_omit_prototype_maps_; }
+
+ protected:
+ virtual bool DataEquals(HValue* other) {
+ HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
+ return first_prototype_unique_id_ == b->first_prototype_unique_id_ &&
+ last_prototype_unique_id_ == b->last_prototype_unique_id_;
+ }
+
+ private:
+ HCheckPrototypeMaps(Handle<JSObject> prototype,
+ Handle<JSObject> holder,
+ Zone* zone,
+ CompilationInfo* info)
+ : prototypes_(2, zone),
+ maps_(2, zone),
+ first_prototype_unique_id_(),
+ last_prototype_unique_id_(),
+ can_omit_prototype_maps_(true) {
+ SetFlag(kUseGVN);
+ SetGVNFlag(kDependsOnMaps);
+ // Keep a list of all objects on the prototype chain up to the holder
+ // and the expected maps.
+ while (true) {
+ prototypes_.Add(prototype, zone);
+ Handle<Map> map(prototype->map());
+ maps_.Add(map, zone);
+ can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
+ if (prototype.is_identical_to(holder)) break;
+ prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
+ }
+ if (can_omit_prototype_maps_) {
+ // Mark in-flight compilation as dependent on those maps.
+ for (int i = 0; i < maps()->length(); i++) {
+ Handle<Map> map = maps()->at(i);
+ map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
+ info);
+ }
+ }
+ }
+
+ ZoneList<Handle<JSObject> > prototypes_;
+ ZoneList<Handle<Map> > maps_;
+ UniqueValueId first_prototype_unique_id_;
+ UniqueValueId last_prototype_unique_id_;
+ bool can_omit_prototype_maps_;
+};
+
+
class InductionVariableData;
@@ -3071,6 +3500,8 @@ class HPhi: public HValue {
induction_variable_data_ = InductionVariableData::ExaminePhi(this);
}
+ virtual void AddInformativeDefinitions();
+
virtual void PrintTo(StringStream* stream);
#ifdef DEBUG
@@ -3124,6 +3555,11 @@ class HPhi: public HValue {
inputs_[index] = value;
}
+ virtual bool IsRelationTrueInternal(NumericRelation relation,
+ HValue* other,
+ int offset = 0,
+ int scale = 0);
+
private:
ZoneList<HValue*> inputs_;
int merged_index_;
@@ -3138,40 +3574,61 @@ class HPhi: public HValue {
};
-// Common base class for HArgumentsObject and HCapturedObject.
-class HDematerializedObject: public HTemplateInstruction<0> {
+class HInductionVariableAnnotation : public HUnaryOperation {
public:
- HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
+ static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
+ NumericRelation relation,
+ int operand_index);
- virtual int OperandCount() { return values_.length(); }
- virtual HValue* OperandAt(int index) const { return values_[index]; }
+ NumericRelation relation() { return relation_; }
+ HValue* induction_base() { return phi_->OperandAt(operand_index_); }
- virtual bool HasEscapingOperandAt(int index) { return false; }
+ virtual int RedefinedOperandIndex() { return 0; }
+ virtual bool IsPurelyInformativeDefinition() { return true; }
virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
+ return representation();
}
- protected:
- virtual void InternalSetOperandAt(int index, HValue* value) {
- values_[index] = value;
+ virtual void PrintDataTo(StringStream* stream);
+
+ virtual bool IsRelationTrueInternal(NumericRelation other_relation,
+ HValue* other_related_value,
+ int offset = 0,
+ int scale = 0) {
+ if (induction_base() == other_related_value) {
+ return relation().CompoundImplies(other_relation, offset, scale);
+ } else {
+ return false;
+ }
}
- // List of values tracked by this marker.
- ZoneList<HValue*> values_;
+ DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation)
private:
- virtual bool IsDeletable() const { return true; }
+ HInductionVariableAnnotation(HPhi* phi,
+ NumericRelation relation,
+ int operand_index)
+ : HUnaryOperation(phi),
+ phi_(phi), relation_(relation), operand_index_(operand_index) {
+ }
+
+ // We need to store the phi both here and in the instruction operand because
+ // the operand can change if a new idef of the phi is added between the phi
+ // and this instruction (inserting an idef updates every use).
+ HPhi* phi_;
+ NumericRelation relation_;
+ int operand_index_;
};
-class HArgumentsObject: public HDematerializedObject {
+class HArgumentsObject: public HTemplateInstruction<0> {
public:
- static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
+ static HArgumentsObject* New(Zone* zone,
+ HValue* context,
+ int count) {
return new(zone) HArgumentsObject(count, zone);
}
- // The values contain a list of all elements in the arguments object
- // including the receiver object, which is skipped when materializing.
const ZoneList<HValue*>* arguments_values() const { return &values_; }
int arguments_count() const { return values_.length(); }
@@ -3180,32 +3637,30 @@ class HArgumentsObject: public HDematerializedObject {
SetOperandAt(values_.length() - 1, argument);
}
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
+ virtual int OperandCount() { return values_.length(); }
+ virtual HValue* OperandAt(int index) const { return values_[index]; }
- private:
- HArgumentsObject(int count, Zone* zone)
- : HDematerializedObject(count, zone) {
- set_representation(Representation::Tagged());
- SetFlag(kIsArguments);
+ virtual bool HasEscapingOperandAt(int index) { return false; }
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::None();
}
-};
+ DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
-class HCapturedObject: public HDematerializedObject {
- public:
- HCapturedObject(int length, Zone* zone)
- : HDematerializedObject(length, zone) {
+ protected:
+ virtual void InternalSetOperandAt(int index, HValue* value) {
+ values_[index] = value;
+ }
+
+ private:
+ HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
set_representation(Representation::Tagged());
- values_.AddBlock(NULL, length, zone); // Resize list.
+ SetFlag(kIsArguments);
}
- // The values contain a list of all in-object properties inside the
- // captured object and is index by field index. Properties in the
- // properties or elements backing store are not tracked here.
- const ZoneList<HValue*>* values() const { return &values_; }
- int length() const { return values_.length(); }
+ virtual bool IsDeletable() const { return true; }
- DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
+ ZoneList<HValue*> values_;
};
@@ -3230,9 +3685,8 @@ class HConstant: public HTemplateInstruction<0> {
}
bool InstanceOf(Handle<Map> map) {
- Handle<Object> constant_object = handle();
- return constant_object->IsJSObject() &&
- Handle<JSObject>::cast(constant_object)->map() == *map;
+ return handle_->IsJSObject() &&
+ Handle<JSObject>::cast(handle_)->map() == *map;
}
bool IsSpecialDouble() const {
@@ -3256,9 +3710,6 @@ class HConstant: public HTemplateInstruction<0> {
}
return false;
}
- if (has_external_reference_value_) {
- return false;
- }
ASSERT(!handle_.is_null());
Heap* heap = isolate()->heap();
@@ -3343,7 +3794,6 @@ class HConstant: public HTemplateInstruction<0> {
return external_reference_value_;
}
- bool HasBooleanValue() const { return type_.IsBoolean(); }
bool BooleanValue() const { return boolean_value_; }
virtual intptr_t Hashcode() {
@@ -3688,6 +4138,12 @@ class HBoundsCheck: public HTemplateInstruction<2> {
HValue* base() { return base_; }
int offset() { return offset_; }
int scale() { return scale_; }
+ bool index_can_increase() {
+ return (responsibility_direction_ & DIRECTION_LOWER) == 0;
+ }
+ bool index_can_decrease() {
+ return (responsibility_direction_ & DIRECTION_UPPER) == 0;
+ }
void ApplyIndexChange();
bool DetectCompoundIndex() {
@@ -3711,6 +4167,11 @@ class HBoundsCheck: public HTemplateInstruction<2> {
return representation();
}
+ virtual bool IsRelationTrueInternal(NumericRelation relation,
+ HValue* related_value,
+ int offset = 0,
+ int scale = 0);
+
virtual void PrintDataTo(StringStream* stream);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
@@ -3721,17 +4182,25 @@ class HBoundsCheck: public HTemplateInstruction<2> {
virtual int RedefinedOperandIndex() { return 0; }
virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
+ virtual void AddInformativeDefinitions();
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
protected:
friend class HBoundsCheckBaseIndexInformation;
+ virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
+ responsibility_direction_ = static_cast<RangeGuaranteeDirection>(
+ responsibility_direction_ | direction);
+ }
+
virtual bool DataEquals(HValue* other) { return true; }
+ virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
bool skip_check_;
HValue* base_;
int offset_;
int scale_;
+ RangeGuaranteeDirection responsibility_direction_;
bool allow_equality_;
private:
@@ -3742,6 +4211,7 @@ class HBoundsCheck: public HTemplateInstruction<2> {
HBoundsCheck(HValue* index, HValue* length)
: skip_check_(false),
base_(NULL), offset_(0), scale_(0),
+ responsibility_direction_(DIRECTION_NONE),
allow_equality_(false) {
SetOperandAt(0, index);
SetOperandAt(1, length);
@@ -3776,10 +4246,22 @@ class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> {
return representation();
}
+ virtual bool IsRelationTrueInternal(NumericRelation relation,
+ HValue* related_value,
+ int offset = 0,
+ int scale = 0);
virtual void PrintDataTo(StringStream* stream);
virtual int RedefinedOperandIndex() { return 0; }
virtual bool IsPurelyInformativeDefinition() { return true; }
+
+ protected:
+ virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
+ bounds_check()->SetResponsibilityForRange(direction);
+ }
+ virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
+ bounds_check()->TryGuaranteeRangeChanging(context);
+ }
};
@@ -3952,6 +4434,8 @@ class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
}
virtual void PrintDataTo(StringStream* stream);
+ virtual void AddInformativeDefinitions();
+
DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
private:
@@ -3960,32 +4444,6 @@ class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
};
-class HCompareHoleAndBranch: public HTemplateControlInstruction<2, 1> {
- public:
- // TODO(danno): make this private when the IfBuilder properly constructs
- // control flow instructions.
- explicit HCompareHoleAndBranch(HValue* object) {
- SetFlag(kFlexibleRepresentation);
- SetFlag(kAllowUndefinedAsNaN);
- SetOperandAt(0, object);
- }
-
- DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
-
- HValue* object() { return OperandAt(0); }
-
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return representation();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
-};
-
-
class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
public:
// TODO(danno): make this private when the IfBuilder properly constructs
@@ -4369,11 +4827,6 @@ class HAdd: public HArithmeticBinaryOperation {
}
}
- virtual void RepresentationChanged(Representation to) {
- if (to.IsTagged()) ClearFlag(kAllowUndefinedAsNaN);
- HArithmeticBinaryOperation::RepresentationChanged(to);
- }
-
DECLARE_CONCRETE_INSTRUCTION(Add)
protected:
@@ -5588,7 +6041,6 @@ class HLoadNamedField: public HTemplateInstruction<2> {
}
bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
- void ClearTypeCheck() { SetOperandAt(1, object()); }
HObjectAccess access() const { return access_; }
Representation field_representation() const {
return access_.representation();
@@ -5646,6 +6098,45 @@ class HLoadNamedField: public HTemplateInstruction<2> {
};
+class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
+ public:
+ HLoadNamedFieldPolymorphic(HValue* context,
+ HValue* object,
+ SmallMapList* types,
+ Handle<String> name,
+ Zone* zone);
+
+ HValue* context() { return OperandAt(0); }
+ HValue* object() { return OperandAt(1); }
+ SmallMapList* types() { return &types_; }
+ Handle<String> name() { return name_; }
+ bool need_generic() { return need_generic_; }
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::Tagged();
+ }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
+
+ static const int kMaxLoadPolymorphism = 4;
+
+ virtual void FinalizeUniqueValueId();
+
+ protected:
+ virtual bool DataEquals(HValue* value);
+
+ private:
+ SmallMapList types_;
+ Handle<String> name_;
+ ZoneList<UniqueValueId> types_unique_ids_;
+ UniqueValueId name_unique_id_;
+ bool need_generic_;
+};
+
+
+
class HLoadNamedGeneric: public HTemplateInstruction<2> {
public:
HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
@@ -5904,7 +6395,7 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> {
};
-class HStoreNamedField: public HTemplateInstruction<3> {
+class HStoreNamedField: public HTemplateInstruction<2> {
public:
DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
HObjectAccess, HValue*);
@@ -5936,35 +6427,24 @@ class HStoreNamedField: public HTemplateInstruction<3> {
return write_barrier_mode_ == SKIP_WRITE_BARRIER;
}
- HValue* object() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
- HValue* transition() const { return OperandAt(2); }
+ HValue* object() { return OperandAt(0); }
+ HValue* value() { return OperandAt(1); }
HObjectAccess access() const { return access_; }
- HValue* new_space_dominator() const { return new_space_dominator_; }
- bool has_transition() const { return has_transition_; }
-
- Handle<Map> transition_map() const {
- if (has_transition()) {
- return Handle<Map>::cast(HConstant::cast(transition())->handle());
- } else {
- return Handle<Map>();
- }
- }
-
- void SetTransition(HConstant* map_constant, CompilationInfo* info) {
- ASSERT(!has_transition()); // Only set once.
- Handle<Map> map = Handle<Map>::cast(map_constant->handle());
+ Handle<Map> transition() const { return transition_; }
+ UniqueValueId transition_unique_id() const { return transition_unique_id_; }
+ void SetTransition(Handle<Map> map, CompilationInfo* info) {
+ ASSERT(transition_.is_null()); // Only set once.
if (map->CanBeDeprecated()) {
map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
}
- SetOperandAt(2, map_constant);
- has_transition_ = true;
+ transition_ = map;
}
+ HValue* new_space_dominator() const { return new_space_dominator_; }
bool NeedsWriteBarrier() {
ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) ||
- !has_transition());
+ transition_.is_null());
if (IsSkipWriteBarrier()) return false;
if (field_representation().IsDouble()) return false;
if (field_representation().IsSmi()) return false;
@@ -5979,6 +6459,10 @@ class HStoreNamedField: public HTemplateInstruction<3> {
return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
}
+ virtual void FinalizeUniqueValueId() {
+ transition_unique_id_ = UniqueValueId(transition_);
+ }
+
Representation field_representation() const {
return access_.representation();
}
@@ -5988,19 +6472,20 @@ class HStoreNamedField: public HTemplateInstruction<3> {
HObjectAccess access,
HValue* val)
: access_(access),
+ transition_(),
+ transition_unique_id_(),
new_space_dominator_(NULL),
- write_barrier_mode_(UPDATE_WRITE_BARRIER),
- has_transition_(false) {
+ write_barrier_mode_(UPDATE_WRITE_BARRIER) {
SetOperandAt(0, obj);
SetOperandAt(1, val);
- SetOperandAt(2, obj);
access.SetGVNFlags(this, true);
}
HObjectAccess access_;
+ Handle<Map> transition_;
+ UniqueValueId transition_unique_id_;
HValue* new_space_dominator_;
- WriteBarrierMode write_barrier_mode_ : 1;
- bool has_transition_ : 1;
+ WriteBarrierMode write_barrier_mode_;
};
@@ -6045,6 +6530,7 @@ class HStoreKeyed
DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
ElementsKind);
+ virtual bool HasEscapingOperandAt(int index) { return index != 0; }
virtual Representation RequiredInputRepresentation(int index) {
// kind_fast: tagged[int32] = tagged
// kind_double: tagged[int32] = double
@@ -6563,11 +7049,8 @@ class HToFastProperties: public HUnaryOperation {
private:
explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
-
- // This instruction is not marked as kChangesMaps, but does
- // change the map of the input operand. Use it only when creating
+ // This instruction is not marked as having side effects, but
+ // changes the map of the input operand. Use it only when creating
// object literals via a runtime call.
ASSERT(value->IsCallRuntime());
#ifdef DEBUG
@@ -6575,6 +7058,7 @@ class HToFastProperties: public HUnaryOperation {
ASSERT(function->function_id == Runtime::kCreateObjectLiteral ||
function->function_id == Runtime::kCreateObjectLiteralShallow);
#endif
+ set_representation(Representation::Tagged());
}
virtual bool IsDeletable() const { return true; }
diff --git a/chromium/v8/src/hydrogen-mark-deoptimize.cc b/chromium/v8/src/hydrogen-mark-deoptimize.cc
index c0236e91cbb..111fcd2ce9b 100644
--- a/chromium/v8/src/hydrogen-mark-deoptimize.cc
+++ b/chromium/v8/src/hydrogen-mark-deoptimize.cc
@@ -34,9 +34,14 @@ void HMarkDeoptimizeOnUndefinedPhase::Run() {
const ZoneList<HPhi*>* phi_list = graph()->phi_list();
for (int i = 0; i < phi_list->length(); i++) {
HPhi* phi = phi_list->at(i);
- if (phi->CheckFlag(HValue::kAllowUndefinedAsNaN) &&
- !phi->CheckUsesForFlag(HValue::kAllowUndefinedAsNaN)) {
- ProcessPhi(phi);
+ if (phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
+ for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
+ HValue* use_value = it.value();
+ if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
+ ProcessPhi(phi);
+ break;
+ }
+ }
}
}
}
@@ -63,22 +68,4 @@ void HMarkDeoptimizeOnUndefinedPhase::ProcessPhi(HPhi* phi) {
}
}
-
-void HComputeChangeUndefinedToNaN::Run() {
- const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
- for (int i = 0; i < blocks->length(); ++i) {
- const HBasicBlock* block(blocks->at(i));
- for (HInstruction* current = block->first(); current != NULL; ) {
- HInstruction* next = current->next();
- if (current->IsChange()) {
- if (HChange::cast(current)->can_convert_undefined_to_nan()) {
- current->SetFlag(HValue::kAllowUndefinedAsNaN);
- }
- }
- current = next;
- }
- }
-}
-
-
} } // namespace v8::internal
diff --git a/chromium/v8/src/hydrogen-mark-deoptimize.h b/chromium/v8/src/hydrogen-mark-deoptimize.h
index 30f35b3dec5..0aa2c2c7540 100644
--- a/chromium/v8/src/hydrogen-mark-deoptimize.h
+++ b/chromium/v8/src/hydrogen-mark-deoptimize.h
@@ -58,18 +58,6 @@ class HMarkDeoptimizeOnUndefinedPhase : public HPhase {
};
-class HComputeChangeUndefinedToNaN : public HPhase {
- public:
- explicit HComputeChangeUndefinedToNaN(HGraph* graph)
- : HPhase("H_Compute change undefined to nan", graph) {}
-
- void Run();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HComputeChangeUndefinedToNaN);
-};
-
-
} } // namespace v8::internal
#endif // V8_HYDROGEN_MARK_DEOPTIMIZE_H_
diff --git a/chromium/v8/src/hydrogen-representation-changes.cc b/chromium/v8/src/hydrogen-representation-changes.cc
index 862457db38c..63b7b4d6ec8 100644
--- a/chromium/v8/src/hydrogen-representation-changes.cc
+++ b/chromium/v8/src/hydrogen-representation-changes.cc
@@ -47,6 +47,8 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
HInstruction* new_value = NULL;
bool is_truncating_to_smi = use_value->CheckFlag(HValue::kTruncatingToSmi);
bool is_truncating_to_int = use_value->CheckFlag(HValue::kTruncatingToInt32);
+ bool allow_undefined_as_nan =
+ use_value->CheckFlag(HValue::kAllowUndefinedAsNaN);
if (value->IsConstant()) {
HConstant* constant = HConstant::cast(value);
// Try to create a new copy of the constant with the new representation.
@@ -59,8 +61,10 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
}
if (new_value == NULL) {
- new_value = new(graph()->zone()) HChange(
- value, to, is_truncating_to_smi, is_truncating_to_int);
+ new_value = new(graph()->zone()) HChange(value, to,
+ is_truncating_to_smi,
+ is_truncating_to_int,
+ allow_undefined_as_nan);
}
new_value->InsertBefore(next);
@@ -123,7 +127,7 @@ void HRepresentationChangesPhase::Run() {
!(input_representation.IsInteger32() &&
use->CheckFlag(HValue::kTruncatingToInt32))) ||
(phi->representation().IsSmi() &&
- !(input_representation.IsSmi() &&
+ !(input_representation.IsSmi() ||
use->CheckFlag(HValue::kTruncatingToSmi)))) {
if (FLAG_trace_representation) {
PrintF("#%d Phi is not truncating because of #%d %s\n",
diff --git a/chromium/v8/src/hydrogen-uint32-analysis.cc b/chromium/v8/src/hydrogen-uint32-analysis.cc
index 835a198d4d8..67219f55dff 100644
--- a/chromium/v8/src/hydrogen-uint32-analysis.cc
+++ b/chromium/v8/src/hydrogen-uint32-analysis.cc
@@ -33,7 +33,11 @@ namespace internal {
bool HUint32AnalysisPhase::IsSafeUint32Use(HValue* val, HValue* use) {
// Operations that operate on bits are safe.
- if (use->IsBitwise() || use->IsShl() || use->IsSar() || use->IsShr()) {
+ if (use->IsBitwise() ||
+ use->IsShl() ||
+ use->IsSar() ||
+ use->IsShr() ||
+ use->IsBitNot()) {
return true;
} else if (use->IsChange() || use->IsSimulate()) {
// Conversions and deoptimization have special support for unt32.
diff --git a/chromium/v8/src/hydrogen.cc b/chromium/v8/src/hydrogen.cc
index ba1de7aa225..aab64d64d45 100644
--- a/chromium/v8/src/hydrogen.cc
+++ b/chromium/v8/src/hydrogen.cc
@@ -834,14 +834,14 @@ void HGraphBuilder::IfBuilder::Else() {
}
-void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
+void HGraphBuilder::IfBuilder::Deopt() {
ASSERT(did_then_);
if (did_else_) {
deopt_else_ = true;
} else {
deopt_then_ = true;
}
- builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
+ builder_->Add<HDeoptimize>(Deoptimizer::EAGER);
}
@@ -966,9 +966,8 @@ void HGraphBuilder::LoopBuilder::EndBody() {
// Push the new increment value on the expression stack to merge into the phi.
builder_->environment()->Push(increment_);
- HBasicBlock* last_block = builder_->current_block();
- last_block->GotoNoSimulate(header_block_);
- header_block_->loop_information()->RegisterBackEdge(last_block);
+ builder_->current_block()->GotoNoSimulate(header_block_);
+ header_block_->loop_information()->RegisterBackEdge(body_block_);
builder_->set_current_block(exit_block_);
// Pop the phi from the expression stack
@@ -1043,9 +1042,9 @@ HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
void HGraphBuilder::FinishExitWithHardDeoptimization(
- const char* reason, HBasicBlock* continuation) {
+ HBasicBlock* continuation) {
PadEnvironmentForContinuation(current_block(), continuation);
- Add<HDeoptimize>(reason, Deoptimizer::EAGER);
+ Add<HDeoptimize>(Deoptimizer::EAGER);
if (graph()->IsInsideNoSideEffectsScope()) {
current_block()->GotoNoSimulate(continuation);
} else {
@@ -1059,14 +1058,12 @@ void HGraphBuilder::PadEnvironmentForContinuation(
HBasicBlock* continuation) {
if (continuation->last_environment() != NULL) {
// When merging from a deopt block to a continuation, resolve differences in
- // environment by pushing constant 0 and popping extra values so that the
- // environments match during the join. Push 0 since it has the most specific
- // representation, and will not influence representation inference of the
- // phi.
+ // environment by pushing undefined and popping extra values so that the
+ // environments match during the join.
int continuation_env_length = continuation->last_environment()->length();
while (continuation_env_length != from->last_environment()->length()) {
if (continuation_env_length > from->last_environment()->length()) {
- from->last_environment()->Push(graph()->GetConstant0());
+ from->last_environment()->Push(graph()->GetConstantUndefined());
} else {
from->last_environment()->Pop();
}
@@ -1117,7 +1114,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
IfBuilder key_checker(this);
key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
key_checker.Then();
- key_checker.ElseDeopt("Key out of capacity range");
+ key_checker.ElseDeopt();
key_checker.End();
HValue* new_capacity = BuildNewElementsCapacity(key);
@@ -1273,7 +1270,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
negative_checker.Then();
HInstruction* result = AddExternalArrayElementAccess(
external_elements, key, val, bounds_check, elements_kind, is_store);
- negative_checker.ElseDeopt("Negative key encountered");
+ negative_checker.ElseDeopt();
length_checker.End();
return result;
} else {
@@ -1635,26 +1632,13 @@ void HGraphBuilder::BuildCopyElements(HValue* from_elements,
from_elements_kind,
ALLOW_RETURN_HOLE);
- ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
- IsFastSmiElementsKind(to_elements_kind))
+ ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind)
? FAST_HOLEY_ELEMENTS : to_elements_kind;
-
- if (IsHoleyElementsKind(from_elements_kind) &&
- from_elements_kind != to_elements_kind) {
- IfBuilder if_hole(this);
- if_hole.If<HCompareHoleAndBranch>(element);
- if_hole.Then();
- HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
- ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double())
- : graph()->GetConstantHole();
- Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
- if_hole.Else();
- HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
- store->SetFlag(HValue::kAllowUndefinedAsNaN);
- if_hole.End();
- } else {
- HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
- store->SetFlag(HValue::kAllowUndefinedAsNaN);
+ HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key,
+ element, holey_kind);
+ // Allow NaN hole values to converted to their tagged counterparts.
+ if (IsFastHoleyElementsKind(to_elements_kind)) {
+ holey_store->SetFlag(HValue::kAllowUndefinedAsNaN);
}
builder.EndBody();
@@ -1741,6 +1725,38 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
}
+HInstruction* HGraphBuilder::BuildUnaryMathOp(
+ HValue* input, Handle<Type> type, Token::Value operation) {
+ // We only handle the numeric cases here
+ type = handle(
+ Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
+
+ switch (operation) {
+ default:
+ UNREACHABLE();
+ case Token::SUB: {
+ HInstruction* instr =
+ NewUncasted<HMul>(input, graph()->GetConstantMinus1());
+ Representation rep = Representation::FromType(type);
+ if (type->Is(Type::None())) {
+ Add<HDeoptimize>(Deoptimizer::SOFT);
+ }
+ if (instr->IsBinaryOperation()) {
+ HBinaryOperation* binop = HBinaryOperation::cast(instr);
+ binop->set_observed_input_representation(1, rep);
+ binop->set_observed_input_representation(2, rep);
+ }
+ return instr;
+ }
+ case Token::BIT_NOT:
+ if (type->Is(Type::None())) {
+ Add<HDeoptimize>(Deoptimizer::SOFT);
+ }
+ return New<HBitNot>(input);
+ }
+}
+
+
void HGraphBuilder::BuildCompareNil(
HValue* value,
Handle<Type> type,
@@ -1773,7 +1789,7 @@ void HGraphBuilder::BuildCompareNil(
// emitted below is the actual monomorphic map.
BuildCheckMap(value, type->Classes().Current());
} else {
- if_nil.Deopt("Too many undetectable types");
+ if_nil.Deopt();
}
}
@@ -2572,7 +2588,7 @@ void ValueContext::ReturnValue(HValue* value) {
// The value is tracked in the bailout environment, and communicated
// through the environment as the result of the expression.
if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
- owner()->Bailout(kBadValueContextForArgumentsValue);
+ owner()->Bailout("bad value context for arguments value");
}
owner()->Push(value);
}
@@ -2624,7 +2640,7 @@ void EffectContext::ReturnContinuation(HIfContinuation* continuation,
void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
ASSERT(!instr->IsControlInstruction());
if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
- return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
+ return owner()->Bailout("bad value context for arguments object value");
}
owner()->AddInstruction(instr);
owner()->Push(instr);
@@ -2637,7 +2653,7 @@ void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
ASSERT(!instr->HasObservableSideEffects());
if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
- return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
+ return owner()->Bailout("bad value context for arguments object value");
}
HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
@@ -2727,7 +2743,7 @@ void TestContext::BuildBranch(HValue* value) {
// branch.
HOptimizedGraphBuilder* builder = owner();
if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
- builder->Bailout(kArgumentsObjectValueInATestContext);
+ builder->Bailout("arguments object value in a test context");
}
if (value->IsConstant()) {
HConstant* constant_value = HConstant::cast(value);
@@ -2773,7 +2789,7 @@ void TestContext::BuildBranch(HValue* value) {
} while (false)
-void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
+void HOptimizedGraphBuilder::Bailout(const char* reason) {
current_info()->set_bailout_reason(reason);
SetStackOverflow();
}
@@ -2832,16 +2848,16 @@ void HOptimizedGraphBuilder::VisitExpressions(
bool HOptimizedGraphBuilder::BuildGraph() {
if (current_info()->function()->is_generator()) {
- Bailout(kFunctionIsAGenerator);
+ Bailout("function is a generator");
return false;
}
Scope* scope = current_info()->scope();
if (scope->HasIllegalRedeclaration()) {
- Bailout(kFunctionWithIllegalRedeclaration);
+ Bailout("function with illegal redeclaration");
return false;
}
if (scope->calls_eval()) {
- Bailout(kFunctionCallsEval);
+ Bailout("function calls eval");
return false;
}
SetUpScope(scope);
@@ -2907,7 +2923,8 @@ bool HOptimizedGraphBuilder::BuildGraph() {
}
-bool HGraph::Optimize(BailoutReason* bailout_reason) {
+bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
+ *bailout_reason = SmartArrayPointer<char>();
OrderBlocks();
AssignDominators();
@@ -2928,20 +2945,19 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
Run<HPropagateDeoptimizingMarkPhase>();
if (!CheckConstPhiUses()) {
- *bailout_reason = kUnsupportedPhiUseOfConstVariable;
+ *bailout_reason = SmartArrayPointer<char>(StrDup(
+ "Unsupported phi use of const variable"));
return false;
}
Run<HRedundantPhiEliminationPhase>();
if (!CheckArgumentsPhiUses()) {
- *bailout_reason = kUnsupportedPhiUseOfArguments;
+ *bailout_reason = SmartArrayPointer<char>(StrDup(
+ "Unsupported phi use of arguments"));
return false;
}
// Remove dead code and phis
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
-
- if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
-
CollectPhis();
if (has_osr()) osr()->FinishOsrValues();
@@ -2965,20 +2981,22 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
+ if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
+
if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
if (FLAG_use_range) Run<HRangeAnalysisPhase>();
- Run<HComputeChangeUndefinedToNaN>();
Run<HComputeMinusZeroChecksPhase>();
// Eliminate redundant stack checks on backwards branches.
Run<HStackCheckEliminationPhase>();
- if (FLAG_array_bounds_checks_elimination) {
+ if (FLAG_idefs) SetupInformativeDefinitions();
+ if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
Run<HBoundsCheckEliminationPhase>();
}
- if (FLAG_array_bounds_checks_hoisting) {
+ if (FLAG_array_bounds_checks_hoisting && !FLAG_idefs) {
Run<HBoundsCheckHoistingPhase>();
}
if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
@@ -2990,6 +3008,50 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
}
+void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) {
+ for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) {
+ HPhi* phi = block->phis()->at(phi_index);
+ phi->AddInformativeDefinitions();
+ phi->SetFlag(HValue::kIDefsProcessingDone);
+ // We do not support phis that "redefine just one operand".
+ ASSERT(!phi->IsInformativeDefinition());
+ }
+
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
+ i->AddInformativeDefinitions();
+ i->SetFlag(HValue::kIDefsProcessingDone);
+ i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions();
+ }
+}
+
+
+// This method is recursive, so if its stack frame is large it could
+// cause a stack overflow.
+// To keep the individual stack frames small we do the actual work inside
+// SetupInformativeDefinitionsInBlock();
+void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) {
+ SetupInformativeDefinitionsInBlock(block);
+ for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
+ SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i));
+ }
+
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
+ if (i->IsBoundsCheck()) {
+ HBoundsCheck* check = HBoundsCheck::cast(i);
+ check->ApplyIndexChange();
+ }
+ }
+}
+
+
+void HGraph::SetupInformativeDefinitions() {
+ HPhase phase("H_Setup informative definitions", this);
+ SetupInformativeDefinitionsRecursively(entry_block());
+}
+
+
void HGraph::RestoreActualValues() {
HPhase phase("H_Restore actual values", this);
@@ -3072,7 +3134,7 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
// not have declarations).
if (scope->arguments() != NULL) {
if (!scope->arguments()->IsStackAllocated()) {
- return Bailout(kContextAllocatedArguments);
+ return Bailout("context-allocated arguments");
}
environment()->Bind(scope->arguments(),
@@ -3093,7 +3155,7 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
if (stmt->scope() != NULL) {
- return Bailout(kScopedBlock);
+ return Bailout("ScopedBlock");
}
BreakAndContinueInfo break_info(stmt);
{ BreakAndContinueScope push(&break_info, this);
@@ -3305,7 +3367,7 @@ void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kWithStatement);
+ return Bailout("WithStatement");
}
@@ -3320,12 +3382,12 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
ZoneList<CaseClause*>* clauses = stmt->cases();
int clause_count = clauses->length();
if (clause_count > kCaseClauseLimit) {
- return Bailout(kSwitchStatementTooManyClauses);
+ return Bailout("SwitchStatement: too many clauses");
}
ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) {
- return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels);
+ return Bailout("SwitchStatement: mixed or non-literal switch labels");
}
HValue* context = environment()->context();
@@ -3371,7 +3433,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
if (!clause->compare_type()->Is(Type::Smi())) {
- Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
HCompareNumericAndBranch* compare_ =
@@ -3617,16 +3679,16 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
ASSERT(current_block()->HasPredecessor());
if (!FLAG_optimize_for_in) {
- return Bailout(kForInStatementOptimizationIsDisabled);
+ return Bailout("ForInStatement optimization is disabled");
}
if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
- return Bailout(kForInStatementIsNotFastCase);
+ return Bailout("ForInStatement is not fast case");
}
if (!stmt->each()->IsVariableProxy() ||
!stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
- return Bailout(kForInStatementWithNonLocalEachVariable);
+ return Bailout("ForInStatement with non-local each variable");
}
Variable* each_var = stmt->each()->AsVariableProxy()->var();
@@ -3720,7 +3782,7 @@ void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kForOfStatement);
+ return Bailout("ForOfStatement");
}
@@ -3728,7 +3790,7 @@ void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kTryCatchStatement);
+ return Bailout("TryCatchStatement");
}
@@ -3737,7 +3799,7 @@ void HOptimizedGraphBuilder::VisitTryFinallyStatement(
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kTryFinallyStatement);
+ return Bailout("TryFinallyStatement");
}
@@ -3745,7 +3807,7 @@ void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kDebuggerStatement);
+ return Bailout("DebuggerStatement");
}
@@ -3791,7 +3853,7 @@ void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral(
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout(kSharedFunctionInfoLiteral);
+ return Bailout("SharedFunctionInfoLiteral");
}
@@ -3871,7 +3933,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
case Variable::UNALLOCATED: {
if (IsLexicalVariableMode(variable->mode())) {
// TODO(rossberg): should this be an ASSERT?
- return Bailout(kReferenceToGlobalLexicalVariable);
+ return Bailout("reference to global lexical variable");
}
// Handle known global constants like 'undefined' specially to avoid a
// load from a global cell for them.
@@ -3928,7 +3990,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
if (value == graph()->GetConstantHole()) {
ASSERT(IsDeclaredVariableMode(variable->mode()) &&
variable->mode() != VAR);
- return Bailout(kReferenceToUninitializedVariable);
+ return Bailout("reference to uninitialized variable");
}
return ast_context()->ReturnValue(value);
}
@@ -3940,7 +4002,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
}
case Variable::LOOKUP:
- return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
+ return Bailout("reference to a variable which requires dynamic lookup");
}
}
@@ -4061,7 +4123,8 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
int* data_size,
int* pointer_size) {
if (boilerplate->map()->is_deprecated()) {
- Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
+ Handle<Object> result =
+ JSObject::TryMigrateInstance(boilerplate);
if (result->IsSmi()) return false;
}
@@ -4238,7 +4301,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
case ObjectLiteral::Property::SETTER:
case ObjectLiteral::Property::GETTER:
- return Bailout(kObjectLiteralWithComplexProperty);
+ return Bailout("Object literal with complex property");
default: UNREACHABLE();
}
}
@@ -4277,7 +4340,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
isolate(), literals, expr->constant_elements());
if (raw_boilerplate.is_null()) {
- return Bailout(kArrayBoilerplateCreationFailed);
+ return Bailout("array boilerplate creation failed");
}
site = isolate()->factory()->NewAllocationSite();
@@ -4369,7 +4432,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
CHECK_ALIVE(VisitForValue(subexpr));
HValue* value = Pop();
- if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
+ if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
elements = AddLoadElements(literal, type_check);
@@ -4450,7 +4513,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
if (proto_result.IsProperty()) {
// If the inherited property could induce readonly-ness, bail out.
if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
- Bailout(kImproperObjectOnPrototypeChainForStore);
+ Bailout("improper object on prototype chain for store");
return NULL;
}
// We only need to check up to the preexisting property.
@@ -4463,9 +4526,9 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
ASSERT(proto->GetPrototype(isolate())->IsNull());
}
ASSERT(proto->IsJSObject());
- BuildCheckPrototypeMaps(
+ Add<HCheckPrototypeMaps>(
Handle<JSObject>(JSObject::cast(map->prototype())),
- Handle<JSObject>(JSObject::cast(proto)));
+ Handle<JSObject>(JSObject::cast(proto)), top_info());
}
HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
@@ -4503,8 +4566,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
if (transition_to_field) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
- HConstant* transition_constant = Add<HConstant>(transition);
- instr->SetTransition(transition_constant, top_info());
+ instr->SetTransition(transition, top_info());
// TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store.
instr->SetGVNFlag(kChangesMaps);
@@ -4620,43 +4682,14 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
- BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
+ Add<HCheckPrototypeMaps>(
+ Handle<JSObject>::cast(prototype), holder, top_info());
HValue* holder_value = Add<HConstant>(holder);
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name), type_check);
}
-// Returns true if an instance of this map can never find a property with this
-// name in its prototype chain. This means all prototypes up to the top are
-// fast and don't have the name in them. It would be good if we could optimize
-// polymorphic loads where the property is sometimes found in the prototype
-// chain.
-static bool PrototypeChainCanNeverResolve(
- Handle<Map> map, Handle<String> name) {
- Isolate* isolate = map->GetIsolate();
- Object* current = map->prototype();
- while (current != isolate->heap()->null_value()) {
- if (current->IsJSGlobalProxy() ||
- current->IsGlobalObject() ||
- !current->IsJSObject() ||
- JSObject::cast(current)->map()->has_named_interceptor() ||
- JSObject::cast(current)->IsAccessCheckNeeded() ||
- !JSObject::cast(current)->HasFastProperties()) {
- return false;
- }
-
- LookupResult lookup(isolate);
- Map* map = JSObject::cast(current)->map();
- map->LookupDescriptor(NULL, *name, &lookup);
- if (lookup.IsFound()) return false;
- if (!lookup.IsCacheable()) return false;
- current = JSObject::cast(current)->GetPrototype();
- }
- return true;
-}
-
-
void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
Property* expr,
HValue* object,
@@ -4664,90 +4697,16 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
Handle<String> name) {
HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
expr, object, types, name);
- if (instr != NULL) {
- instr->set_position(expr->position());
- return ast_context()->ReturnInstruction(instr, expr->id());
- }
-
- // Something did not match; must use a polymorphic load.
- int count = 0;
- HBasicBlock* join = NULL;
- for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
- Handle<Map> map = types->at(i);
- LookupResult lookup(isolate());
- if (ComputeLoadStoreField(map, name, &lookup, false) ||
- (lookup.IsCacheable() &&
- !map->is_dictionary_map() &&
- !map->has_named_interceptor() &&
- (lookup.IsConstant() ||
- (!lookup.IsFound() &&
- PrototypeChainCanNeverResolve(map, name))))) {
- if (count == 0) {
- BuildCheckHeapObject(object);
- join = graph()->CreateBasicBlock();
- }
- ++count;
- HBasicBlock* if_true = graph()->CreateBasicBlock();
- HBasicBlock* if_false = graph()->CreateBasicBlock();
- HCompareMap* compare =
- new(zone()) HCompareMap(object, map, if_true, if_false);
- current_block()->Finish(compare);
-
- set_current_block(if_true);
-
- // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
- if (lookup.IsField()) {
- HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
- HLoadNamedField* load = BuildLoadNamedField(object, access, compare);
- load->set_position(expr->position());
- AddInstruction(load);
- if (!ast_context()->IsEffect()) Push(load);
- } else if (lookup.IsConstant()) {
- Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
- HConstant* hconstant = Add<HConstant>(constant);
- if (!ast_context()->IsEffect()) Push(hconstant);
- } else {
- ASSERT(!lookup.IsFound());
- if (map->prototype()->IsJSObject()) {
- Handle<JSObject> prototype(JSObject::cast(map->prototype()));
- Handle<JSObject> holder = prototype;
- while (holder->map()->prototype()->IsJSObject()) {
- holder = handle(JSObject::cast(holder->map()->prototype()));
- }
- BuildCheckPrototypeMaps(prototype, holder);
- }
- if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
- }
-
- current_block()->Goto(join);
- set_current_block(if_false);
- }
- }
-
- // Finish up. Unconditionally deoptimize if we've handled all the maps we
- // know about and do not want to handle ones we've never seen. Otherwise
- // use a generic IC.
- if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
- FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
- } else {
- HInstruction* load = BuildLoadNamedGeneric(object, name, expr);
- load->set_position(expr->position());
- AddInstruction(load);
- if (!ast_context()->IsEffect()) Push(load);
-
- if (join != NULL) {
- current_block()->Goto(join);
- } else {
- Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
- return;
- }
+ if (instr == NULL) {
+ // Something did not match; must use a polymorphic load.
+ BuildCheckHeapObject(object);
+ HValue* context = environment()->context();
+ instr = new(zone()) HLoadNamedFieldPolymorphic(
+ context, object, types, name, zone());
}
- ASSERT(join != NULL);
- join->SetJoinId(expr->id());
- set_current_block(join);
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+ instr->set_position(expr->position());
+ return ast_context()->ReturnInstruction(instr, expr->id());
}
@@ -4866,7 +4825,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
- FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
+ FinishExitWithHardDeoptimization(join);
} else {
HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
instr->set_position(position);
@@ -4914,10 +4873,7 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
HValue* value = environment()->ExpressionStackAt(0);
HValue* object = environment()->ExpressionStackAt(1);
- if (expr->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient type feedback for property assignment",
- Deoptimizer::SOFT);
- }
+ if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT);
return BuildStoreNamed(expr, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, value, value);
} else {
@@ -4963,8 +4919,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
}
builder.Then();
builder.Else();
- Add<HDeoptimize>("Constant global variable assignment",
- Deoptimizer::EAGER);
+ Add<HDeoptimize>(Deoptimizer::EAGER);
builder.End();
}
HInstruction* instr =
@@ -5062,7 +5017,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
if (proxy != NULL) {
Variable* var = proxy->var();
if (var->mode() == LET) {
- return Bailout(kUnsupportedLetCompoundAssignment);
+ return Bailout("unsupported let compound assignment");
}
CHECK_ALIVE(VisitForValue(operation));
@@ -5078,7 +5033,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
case Variable::PARAMETER:
case Variable::LOCAL:
if (var->mode() == CONST) {
- return Bailout(kUnsupportedConstCompoundAssignment);
+ return Bailout("unsupported const compound assignment");
}
BindIfLive(var, Top());
break;
@@ -5094,7 +5049,8 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
- Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
+ Bailout(
+ "assignment to parameter, function uses arguments object");
}
}
}
@@ -5125,7 +5081,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
}
case Variable::LOOKUP:
- return Bailout(kCompoundAssignmentToLookupSlot);
+ return Bailout("compound assignment to lookup slot");
}
return ast_context()->ReturnValue(Pop());
@@ -5173,7 +5129,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
}
- return BuildStoreNamed(expr, expr->id(), expr->position(),
+ return BuildStoreNamed(prop, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, instr, instr);
} else {
// Keyed property.
@@ -5214,7 +5170,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
}
} else {
- return Bailout(kInvalidLhsInCompoundAssignment);
+ return Bailout("invalid lhs in compound assignment");
}
}
@@ -5251,11 +5207,11 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
}
} else if (var->mode() == CONST_HARMONY) {
if (expr->op() != Token::INIT_CONST_HARMONY) {
- return Bailout(kNonInitializerAssignmentToConst);
+ return Bailout("non-initializer assignment to const");
}
}
- if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
+ if (proxy->IsArguments()) return Bailout("assignment to arguments");
// Handle the assignment.
switch (var->location()) {
@@ -5274,7 +5230,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
if (var->mode() == LET && expr->op() == Token::ASSIGN) {
HValue* env_value = environment()->Lookup(var);
if (env_value == graph()->GetConstantHole()) {
- return Bailout(kAssignmentToLetVariableBeforeInitialization);
+ return Bailout("assignment to let variable before initialization");
}
}
// We do not allow the arguments object to occur in a context where it
@@ -5296,7 +5252,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
- return Bailout(kAssignmentToParameterInArgumentsObject);
+ return Bailout("assignment to parameter in arguments object");
}
}
}
@@ -5337,10 +5293,10 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
}
case Variable::LOOKUP:
- return Bailout(kAssignmentToLOOKUPVariable);
+ return Bailout("assignment to LOOKUP variable");
}
} else {
- return Bailout(kInvalidLeftHandSideInAssignment);
+ return Bailout("invalid left-hand side in assignment");
}
}
@@ -5405,8 +5361,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
Handle<String> name,
Property* expr) {
if (expr->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient feedback for generic named load",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
HValue* context = environment()->context();
return new(zone()) HLoadNamedGeneric(context, object, name);
@@ -5463,7 +5418,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
HCheckMaps* type_check = AddCheckMap(object, map);
- BuildCheckPrototypeMaps(prototype, holder);
+ Add<HCheckPrototypeMaps>(prototype, holder, top_info());
HValue* holder_value = Add<HConstant>(holder);
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name), type_check);
@@ -5475,7 +5430,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
AddCheckMap(object, map);
- BuildCheckPrototypeMaps(prototype, holder);
+ Add<HCheckPrototypeMaps>(prototype, holder, top_info());
Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
return New<HConstant>(constant);
}
@@ -5511,7 +5466,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
- BuildCheckPrototypeMaps(prototype, object_prototype);
+ Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info());
load_mode = ALLOW_RETURN_HOLE;
graph()->MarkDependsOnEmptyArrayProtoElements();
}
@@ -5724,8 +5679,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
// Deopt if none of the cases matched.
NoObservableSideEffectsScope scope(this);
- FinishExitWithHardDeoptimization("Unknown type in polymorphic element access",
- join);
+ FinishExitWithHardDeoptimization(join);
set_current_block(join);
return is_store ? NULL : Pop();
}
@@ -5761,14 +5715,12 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
} else {
if (is_store) {
if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient feedback for keyed store",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
instr = BuildStoreKeyedGeneric(obj, key, val);
} else {
if (expr->AsProperty()->IsUninitialized()) {
- Add<HDeoptimize>("Insufficient feedback for keyed load",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
}
instr = BuildLoadKeyedGeneric(obj, key);
}
@@ -5961,38 +5913,11 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
}
-void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
- CompilationInfo* info) {
- HConstant* constant_value = New<HConstant>(constant);
-
- if (constant->map()->CanOmitMapChecks()) {
- constant->map()->AddDependentCompilationInfo(
- DependentCode::kPrototypeCheckGroup, info);
- return;
- }
-
- AddInstruction(constant_value);
- HCheckMaps* check =
- Add<HCheckMaps>(constant_value, handle(constant->map()), info);
- check->ClearGVNFlag(kDependsOnElementsKind);
-}
-
-
-void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
- Handle<JSObject> holder) {
- BuildConstantMapCheck(prototype, top_info());
- while (!prototype.is_identical_to(holder)) {
- prototype = handle(JSObject::cast(prototype->GetPrototype()));
- BuildConstantMapCheck(prototype, top_info());
- }
-}
-
-
void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
Handle<Map> receiver_map) {
if (!holder.is_null()) {
Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
- BuildCheckPrototypeMaps(prototype, holder);
+ Add<HCheckPrototypeMaps>(prototype, holder, top_info());
}
}
@@ -6215,7 +6140,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
// that the environment stack matches the depth on deopt that it otherwise
// would have had after a successful call.
Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1));
- FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
+ FinishExitWithHardDeoptimization(join);
} else {
HValue* context = environment()->context();
HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
@@ -6364,7 +6289,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
if (target_info.isolate()->has_pending_exception()) {
// Parse or scope error, never optimize this function.
SetStackOverflow();
- target_shared->DisableOptimization(kParseScopeError);
+ target_shared->DisableOptimization("parse/scope error");
}
TraceInline(target, caller, "parse failure");
return false;
@@ -6503,7 +6428,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
// Bail out if the inline function did, as we cannot residualize a call
// instead.
TraceInline(target, caller, "inline graph construction failed");
- target_shared->DisableOptimization(kInliningBailedOut);
+ target_shared->DisableOptimization("inlining bailed out");
inline_bailout_ = true;
delete target_state;
return true;
@@ -6733,9 +6658,9 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
HValue* string = Pop();
HValue* context = environment()->context();
ASSERT(!expr->holder().is_null());
- BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
+ Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck(
STRING_CHECK, expr->holder()->GetIsolate()),
- expr->holder());
+ expr->holder(), top_info());
HInstruction* char_code =
BuildStringCharCodeAt(string, index);
if (id == kStringCharCodeAt) {
@@ -7048,7 +6973,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
} else {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
- return Bailout(kPossibleDirectCallToEval);
+ return Bailout("possible direct call to eval");
}
bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
@@ -7316,7 +7241,7 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
if (expr->is_jsruntime()) {
- return Bailout(kCallToAJavaScriptRuntimeFunction);
+ return Bailout("call to a JavaScript runtime function");
}
const Runtime::Function* function = expr->function();
@@ -7356,6 +7281,8 @@ void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
case Token::DELETE: return VisitDelete(expr);
case Token::VOID: return VisitVoid(expr);
case Token::TYPEOF: return VisitTypeof(expr);
+ case Token::SUB: return VisitSub(expr);
+ case Token::BIT_NOT: return VisitBitNot(expr);
case Token::NOT: return VisitNot(expr);
default: UNREACHABLE();
}
@@ -7381,7 +7308,7 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
} else if (proxy != NULL) {
Variable* var = proxy->var();
if (var->IsUnallocated()) {
- Bailout(kDeleteWithGlobalVariable);
+ Bailout("delete with global variable");
} else if (var->IsStackAllocated() || var->IsContextSlot()) {
// Result of deleting non-global variables is false. 'this' is not
// really a variable, though we implement it as one. The
@@ -7391,7 +7318,7 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
: graph()->GetConstantFalse();
return ast_context()->ReturnValue(value);
} else {
- Bailout(kDeleteWithNonGlobalVariable);
+ Bailout("delete with non-global variable");
}
} else {
// Result of deleting non-property, non-variable reference is true.
@@ -7417,6 +7344,24 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
}
+void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
+ CHECK_ALIVE(VisitForValue(expr->expression()));
+ Handle<Type> operand_type = expr->expression()->bounds().lower;
+ HValue* value = TruncateToNumber(Pop(), &operand_type);
+ HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
+ return ast_context()->ReturnInstruction(instr, expr->id());
+}
+
+
+void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
+ CHECK_ALIVE(VisitForValue(expr->expression()));
+ Handle<Type> operand_type = expr->expression()->bounds().lower;
+ HValue* value = TruncateToNumber(Pop(), &operand_type);
+ HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
+ return ast_context()->ReturnInstruction(instr, expr->id());
+}
+
+
void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
if (ast_context()->IsTest()) {
TestContext* context = TestContext::cast(ast_context());
@@ -7505,7 +7450,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
VariableProxy* proxy = target->AsVariableProxy();
Property* prop = target->AsProperty();
if (proxy == NULL && prop == NULL) {
- return Bailout(kInvalidLhsInCountOperation);
+ return Bailout("invalid lhs in count operation");
}
// Match the full code generator stack by simulating an extra stack
@@ -7519,7 +7464,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
if (proxy != NULL) {
Variable* var = proxy->var();
if (var->mode() == CONST) {
- return Bailout(kUnsupportedCountOperationWithConst);
+ return Bailout("unsupported count operation with const");
}
// Argument of the count operation is a variable, not a property.
ASSERT(prop == NULL);
@@ -7553,7 +7498,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
- return Bailout(kAssignmentToParameterInArgumentsObject);
+ return Bailout("assignment to parameter in arguments object");
}
}
}
@@ -7570,7 +7515,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
case Variable::LOOKUP:
- return Bailout(kLookupVariableInCountOperation);
+ return Bailout("lookup variable in count operation");
}
} else {
@@ -7613,7 +7558,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
after = BuildIncrement(returns_original_input, expr);
HValue* result = returns_original_input ? Pop() : after;
- return BuildStoreNamed(expr, expr->id(), expr->position(),
+ return BuildStoreNamed(prop, expr->id(), expr->position(),
expr->AssignmentId(), prop, object, after, result);
} else {
// Keyed property.
@@ -7775,14 +7720,12 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
}
if (left_type->Is(Type::None())) {
- Add<HDeoptimize>("Insufficient type feedback for left side",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
// TODO(rossberg): we should be able to get rid of non-continuous defaults.
left_type = handle(Type::Any(), isolate());
}
if (right_type->Is(Type::None())) {
- Add<HDeoptimize>("Insufficient type feedback for right side",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
right_type = handle(Type::Any(), isolate());
}
HInstruction* instr = NULL;
@@ -8132,8 +8075,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Cases handled below depend on collected type feedback. They should
// soft deoptimize when there is no type feedback.
if (combined_type->Is(Type::None())) {
- Add<HDeoptimize>("insufficient type feedback for combined type",
- Deoptimizer::SOFT);
+ Add<HDeoptimize>(Deoptimizer::SOFT);
combined_type = left_type = right_type = handle(Type::Any(), isolate());
}
@@ -8162,7 +8104,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
}
}
default:
- return Bailout(kUnsupportedNonPrimitiveCompare);
+ return Bailout("Unsupported non-primitive compare");
}
} else if (combined_type->Is(Type::InternalizedString()) &&
Token::IsEqualityOp(op)) {
@@ -8625,7 +8567,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
}
break;
case Variable::LOOKUP:
- return Bailout(kUnsupportedLookupSlotInDeclaration);
+ return Bailout("unsupported lookup slot in declaration");
}
}
@@ -8663,7 +8605,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
break;
}
case Variable::LOOKUP:
- return Bailout(kUnsupportedLookupSlotInDeclaration);
+ return Bailout("unsupported lookup slot in declaration");
}
}
@@ -8784,7 +8726,7 @@ void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
+ return Bailout("inlined runtime function: IsNonNegativeSmi");
}
@@ -8800,7 +8742,8 @@ void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
+ return Bailout(
+ "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
}
@@ -8854,7 +8797,7 @@ void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
// The special form detected by IsClassOfTest is detected before we get here
// and does not cause a bailout.
- return Bailout(kInlinedRuntimeFunctionClassOf);
+ return Bailout("inlined runtime function: ClassOf");
}
@@ -9071,7 +9014,7 @@ void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
// Support for fast native caches.
void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionGetFromCache);
+ return Bailout("inlined runtime function: GetFromCache");
}
@@ -9201,7 +9144,7 @@ void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
// Check whether two RegExps are equivalent
void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
+ return Bailout("inlined runtime function: IsRegExpEquivalent");
}
@@ -9215,18 +9158,18 @@ void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin);
+ return Bailout("inlined runtime function: FastAsciiArrayJoin");
}
// Support for generators.
void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionGeneratorNext);
+ return Bailout("inlined runtime function: GeneratorNext");
}
void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
- return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
+ return Bailout("inlined runtime function: GeneratorThrow");
}
diff --git a/chromium/v8/src/hydrogen.h b/chromium/v8/src/hydrogen.h
index 004aa16a878..20dc1a3e0ec 100644
--- a/chromium/v8/src/hydrogen.h
+++ b/chromium/v8/src/hydrogen.h
@@ -368,7 +368,7 @@ class HGraph: public ZoneObject {
return NULL;
}
- bool Optimize(BailoutReason* bailout_reason);
+ bool Optimize(SmartArrayPointer<char>* bailout_reason);
#ifdef DEBUG
void Verify(bool do_full_verify) const;
@@ -1266,8 +1266,7 @@ class HGraphBuilder {
void PushAndAdd(HInstruction* instr);
- void FinishExitWithHardDeoptimization(const char* reason,
- HBasicBlock* continuation);
+ void FinishExitWithHardDeoptimization(HBasicBlock* continuation);
void AddIncrementCounter(StatsCounter* counter,
HValue* context);
@@ -1371,10 +1370,10 @@ class HGraphBuilder {
void Else();
void End();
- void Deopt(const char* reason);
- void ElseDeopt(const char* reason) {
+ void Deopt();
+ void ElseDeopt() {
Else();
- Deopt(reason);
+ Deopt();
}
void Return(HValue* value);
@@ -1533,6 +1532,9 @@ class HGraphBuilder {
ElementsKind kind,
int length);
+ HInstruction* BuildUnaryMathOp(
+ HValue* value, Handle<Type> type, Token::Value token);
+
void BuildCompareNil(
HValue* value,
Handle<Type> type,
@@ -1543,10 +1545,6 @@ class HGraphBuilder {
int previous_object_size,
HValue* payload);
- void BuildConstantMapCheck(Handle<JSObject> constant, CompilationInfo* info);
- void BuildCheckPrototypeMaps(Handle<JSObject> prototype,
- Handle<JSObject> holder);
-
HInstruction* BuildGetNativeContext();
HInstruction* BuildGetArrayFunction();
@@ -1564,13 +1562,13 @@ class HGraphBuilder {
template<>
inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
- const char* reason, Deoptimizer::BailoutType type) {
+ Deoptimizer::BailoutType type) {
if (type == Deoptimizer::SOFT) {
isolate()->counters()->soft_deopts_requested()->Increment();
if (FLAG_always_opt) return NULL;
}
if (current_block()->IsDeoptimizing()) return NULL;
- HDeoptimize* instr = New<HDeoptimize>(reason, type);
+ HDeoptimize* instr = New<HDeoptimize>(type);
AddInstruction(instr);
if (type == Deoptimizer::SOFT) {
isolate()->counters()->soft_deopts_inserted()->Increment();
@@ -1583,8 +1581,8 @@ inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
template<>
inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
- const char* reason, Deoptimizer::BailoutType type) {
- return static_cast<HDeoptimize*>(AddUncasted<HDeoptimize>(reason, type));
+ Deoptimizer::BailoutType type) {
+ return static_cast<HDeoptimize*>(AddUncasted<HDeoptimize>(type));
}
@@ -1709,7 +1707,7 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
HValue* context() { return environment()->context(); }
- void Bailout(BailoutReason reason);
+ void Bailout(const char* reason);
HBasicBlock* CreateJoin(HBasicBlock* first,
HBasicBlock* second,
@@ -1790,6 +1788,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
void VisitDelete(UnaryOperation* expr);
void VisitVoid(UnaryOperation* expr);
void VisitTypeof(UnaryOperation* expr);
+ void VisitSub(UnaryOperation* expr);
+ void VisitBitNot(UnaryOperation* expr);
void VisitNot(UnaryOperation* expr);
void VisitComma(BinaryOperation* expr);
diff --git a/chromium/v8/src/i18n.cc b/chromium/v8/src/i18n.cc
deleted file mode 100644
index 5cfe4c43b2f..00000000000
--- a/chromium/v8/src/i18n.cc
+++ /dev/null
@@ -1,938 +0,0 @@
-// 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.
-// limitations under the License.
-
-#include "i18n.h"
-
-#include "unicode/calendar.h"
-#include "unicode/coll.h"
-#include "unicode/curramt.h"
-#include "unicode/dcfmtsym.h"
-#include "unicode/decimfmt.h"
-#include "unicode/dtfmtsym.h"
-#include "unicode/dtptngen.h"
-#include "unicode/locid.h"
-#include "unicode/numfmt.h"
-#include "unicode/numsys.h"
-#include "unicode/smpdtfmt.h"
-#include "unicode/timezone.h"
-#include "unicode/uchar.h"
-#include "unicode/ucol.h"
-#include "unicode/ucurr.h"
-#include "unicode/unum.h"
-#include "unicode/uversion.h"
-
-namespace v8 {
-namespace internal {
-
-namespace {
-
-bool ExtractStringSetting(Isolate* isolate,
- Handle<JSObject> options,
- const char* key,
- icu::UnicodeString* setting) {
- Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
- MaybeObject* maybe_object = options->GetProperty(*str);
- Object* object;
- if (maybe_object->ToObject(&object) && object->IsString()) {
- v8::String::Utf8Value utf8_string(
- v8::Utils::ToLocal(Handle<String>(String::cast(object))));
- *setting = icu::UnicodeString::fromUTF8(*utf8_string);
- return true;
- }
- return false;
-}
-
-
-bool ExtractIntegerSetting(Isolate* isolate,
- Handle<JSObject> options,
- const char* key,
- int32_t* value) {
- Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
- MaybeObject* maybe_object = options->GetProperty(*str);
- Object* object;
- if (maybe_object->ToObject(&object) && object->IsNumber()) {
- object->ToInt32(value);
- return true;
- }
- return false;
-}
-
-
-bool ExtractBooleanSetting(Isolate* isolate,
- Handle<JSObject> options,
- const char* key,
- bool* value) {
- Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
- MaybeObject* maybe_object = options->GetProperty(*str);
- Object* object;
- if (maybe_object->ToObject(&object) && object->IsBoolean()) {
- *value = object->BooleanValue();
- return true;
- }
- return false;
-}
-
-
-icu::SimpleDateFormat* CreateICUDateFormat(
- Isolate* isolate,
- const icu::Locale& icu_locale,
- Handle<JSObject> options) {
- // Create time zone as specified by the user. We have to re-create time zone
- // since calendar takes ownership.
- icu::TimeZone* tz = NULL;
- icu::UnicodeString timezone;
- if (ExtractStringSetting(isolate, options, "timeZone", &timezone)) {
- tz = icu::TimeZone::createTimeZone(timezone);
- } else {
- tz = icu::TimeZone::createDefault();
- }
-
- // Create a calendar using locale, and apply time zone to it.
- UErrorCode status = U_ZERO_ERROR;
- icu::Calendar* calendar =
- icu::Calendar::createInstance(tz, icu_locale, status);
-
- // Make formatter from skeleton. Calendar and numbering system are added
- // to the locale as Unicode extension (if they were specified at all).
- icu::SimpleDateFormat* date_format = NULL;
- icu::UnicodeString skeleton;
- if (ExtractStringSetting(isolate, options, "skeleton", &skeleton)) {
- icu::DateTimePatternGenerator* generator =
- icu::DateTimePatternGenerator::createInstance(icu_locale, status);
- icu::UnicodeString pattern;
- if (U_SUCCESS(status)) {
- pattern = generator->getBestPattern(skeleton, status);
- delete generator;
- }
-
- date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
- if (U_SUCCESS(status)) {
- date_format->adoptCalendar(calendar);
- }
- }
-
- if (U_FAILURE(status)) {
- delete calendar;
- delete date_format;
- date_format = NULL;
- }
-
- return date_format;
-}
-
-
-void SetResolvedDateSettings(Isolate* isolate,
- const icu::Locale& icu_locale,
- icu::SimpleDateFormat* date_format,
- Handle<JSObject> resolved) {
- UErrorCode status = U_ZERO_ERROR;
- icu::UnicodeString pattern;
- date_format->toPattern(pattern);
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
- isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
- pattern.length())),
- NONE,
- kNonStrictMode);
-
- // Set time zone and calendar.
- const icu::Calendar* calendar = date_format->getCalendar();
- const char* calendar_name = calendar->getType();
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("calendar")),
- isolate->factory()->NewStringFromAscii(CStrVector(calendar_name)),
- NONE,
- kNonStrictMode);
-
- const icu::TimeZone& tz = calendar->getTimeZone();
- icu::UnicodeString time_zone;
- tz.getID(time_zone);
-
- icu::UnicodeString canonical_time_zone;
- icu::TimeZone::getCanonicalID(time_zone, canonical_time_zone, status);
- if (U_SUCCESS(status)) {
- if (canonical_time_zone == UNICODE_STRING_SIMPLE("Etc/GMT")) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
- isolate->factory()->NewStringFromAscii(CStrVector("UTC")),
- NONE,
- kNonStrictMode);
- } else {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
- isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(
- canonical_time_zone.getBuffer()),
- canonical_time_zone.length())),
- NONE,
- kNonStrictMode);
- }
- }
-
- // Ugly hack. ICU doesn't expose numbering system in any way, so we have
- // to assume that for given locale NumberingSystem constructor produces the
- // same digits as NumberFormat/Calendar would.
- status = U_ZERO_ERROR;
- icu::NumberingSystem* numbering_system =
- icu::NumberingSystem::createInstance(icu_locale, status);
- if (U_SUCCESS(status)) {
- const char* ns = numbering_system->getName();
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->NewStringFromAscii(CStrVector(ns)),
- NONE,
- kNonStrictMode);
- } else {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->undefined_value(),
- NONE,
- kNonStrictMode);
- }
- delete numbering_system;
-
- // Set the locale
- char result[ULOC_FULLNAME_CAPACITY];
- status = U_ZERO_ERROR;
- uloc_toLanguageTag(
- icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
- if (U_SUCCESS(status)) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
- NONE,
- kNonStrictMode);
- } else {
- // This would never happen, since we got the locale from ICU.
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
- NONE,
- kNonStrictMode);
- }
-}
-
-
-template<int internal_fields, EternalHandles::SingletonHandle field>
-Handle<ObjectTemplateInfo> GetEternal(Isolate* isolate) {
- if (isolate->eternal_handles()->Exists(field)) {
- return Handle<ObjectTemplateInfo>::cast(
- isolate->eternal_handles()->GetSingleton(field));
- }
- v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
- raw_template->SetInternalFieldCount(internal_fields);
- return Handle<ObjectTemplateInfo>::cast(
- isolate->eternal_handles()->CreateSingleton(
- isolate,
- *v8::Utils::OpenHandle(*raw_template),
- field));
-}
-
-
-icu::DecimalFormat* CreateICUNumberFormat(
- Isolate* isolate,
- const icu::Locale& icu_locale,
- Handle<JSObject> options) {
- // Make formatter from options. Numbering system is added
- // to the locale as Unicode extension (if it was specified at all).
- UErrorCode status = U_ZERO_ERROR;
- icu::DecimalFormat* number_format = NULL;
- icu::UnicodeString style;
- icu::UnicodeString currency;
- if (ExtractStringSetting(isolate, options, "style", &style)) {
- if (style == UNICODE_STRING_SIMPLE("currency")) {
- icu::UnicodeString display;
- ExtractStringSetting(isolate, options, "currency", &currency);
- ExtractStringSetting(isolate, options, "currencyDisplay", &display);
-
-#if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
- icu::NumberFormat::EStyles format_style;
- if (display == UNICODE_STRING_SIMPLE("code")) {
- format_style = icu::NumberFormat::kIsoCurrencyStyle;
- } else if (display == UNICODE_STRING_SIMPLE("name")) {
- format_style = icu::NumberFormat::kPluralCurrencyStyle;
- } else {
- format_style = icu::NumberFormat::kCurrencyStyle;
- }
-#else // ICU version is 4.8 or above (we ignore versions below 4.0).
- UNumberFormatStyle format_style;
- if (display == UNICODE_STRING_SIMPLE("code")) {
- format_style = UNUM_CURRENCY_ISO;
- } else if (display == UNICODE_STRING_SIMPLE("name")) {
- format_style = UNUM_CURRENCY_PLURAL;
- } else {
- format_style = UNUM_CURRENCY;
- }
-#endif
-
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createInstance(icu_locale, format_style, status));
- } else if (style == UNICODE_STRING_SIMPLE("percent")) {
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createPercentInstance(icu_locale, status));
- if (U_FAILURE(status)) {
- delete number_format;
- return NULL;
- }
- // Make sure 1.1% doesn't go into 2%.
- number_format->setMinimumFractionDigits(1);
- } else {
- // Make a decimal instance by default.
- number_format = static_cast<icu::DecimalFormat*>(
- icu::NumberFormat::createInstance(icu_locale, status));
- }
- }
-
- if (U_FAILURE(status)) {
- delete number_format;
- return NULL;
- }
-
- // Set all options.
- if (!currency.isEmpty()) {
- number_format->setCurrency(currency.getBuffer(), status);
- }
-
- int32_t digits;
- if (ExtractIntegerSetting(
- isolate, options, "minimumIntegerDigits", &digits)) {
- number_format->setMinimumIntegerDigits(digits);
- }
-
- if (ExtractIntegerSetting(
- isolate, options, "minimumFractionDigits", &digits)) {
- number_format->setMinimumFractionDigits(digits);
- }
-
- if (ExtractIntegerSetting(
- isolate, options, "maximumFractionDigits", &digits)) {
- number_format->setMaximumFractionDigits(digits);
- }
-
- bool significant_digits_used = false;
- if (ExtractIntegerSetting(
- isolate, options, "minimumSignificantDigits", &digits)) {
- number_format->setMinimumSignificantDigits(digits);
- significant_digits_used = true;
- }
-
- if (ExtractIntegerSetting(
- isolate, options, "maximumSignificantDigits", &digits)) {
- number_format->setMaximumSignificantDigits(digits);
- significant_digits_used = true;
- }
-
- number_format->setSignificantDigitsUsed(significant_digits_used);
-
- bool grouping;
- if (ExtractBooleanSetting(isolate, options, "useGrouping", &grouping)) {
- number_format->setGroupingUsed(grouping);
- }
-
- // Set rounding mode.
- number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
-
- return number_format;
-}
-
-
-void SetResolvedNumberSettings(Isolate* isolate,
- const icu::Locale& icu_locale,
- icu::DecimalFormat* number_format,
- Handle<JSObject> resolved) {
- icu::UnicodeString pattern;
- number_format->toPattern(pattern);
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
- isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
- pattern.length())),
- NONE,
- kNonStrictMode);
-
- // Set resolved currency code in options.currency if not empty.
- icu::UnicodeString currency(number_format->getCurrency());
- if (!currency.isEmpty()) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("currency")),
- isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(currency.getBuffer()),
- currency.length())),
- NONE,
- kNonStrictMode);
- }
-
- // Ugly hack. ICU doesn't expose numbering system in any way, so we have
- // to assume that for given locale NumberingSystem constructor produces the
- // same digits as NumberFormat/Calendar would.
- UErrorCode status = U_ZERO_ERROR;
- icu::NumberingSystem* numbering_system =
- icu::NumberingSystem::createInstance(icu_locale, status);
- if (U_SUCCESS(status)) {
- const char* ns = numbering_system->getName();
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->NewStringFromAscii(CStrVector(ns)),
- NONE,
- kNonStrictMode);
- } else {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
- isolate->factory()->undefined_value(),
- NONE,
- kNonStrictMode);
- }
- delete numbering_system;
-
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("useGrouping")),
- isolate->factory()->ToBoolean(number_format->isGroupingUsed()),
- NONE,
- kNonStrictMode);
-
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("minimumIntegerDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMinimumIntegerDigits()),
- NONE,
- kNonStrictMode);
-
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("minimumFractionDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMinimumFractionDigits()),
- NONE,
- kNonStrictMode);
-
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("maximumFractionDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMaximumFractionDigits()),
- NONE,
- kNonStrictMode);
-
- Handle<String> key = isolate->factory()->NewStringFromAscii(
- CStrVector("minimumSignificantDigits"));
- if (resolved->HasLocalProperty(*key)) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("minimumSignificantDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMinimumSignificantDigits()),
- NONE,
- kNonStrictMode);
- }
-
- key = isolate->factory()->NewStringFromAscii(
- CStrVector("maximumSignificantDigits"));
- if (resolved->HasLocalProperty(*key)) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(
- CStrVector("maximumSignificantDigits")),
- isolate->factory()->NewNumberFromInt(
- number_format->getMaximumSignificantDigits()),
- NONE,
- kNonStrictMode);
- }
-
- // Set the locale
- char result[ULOC_FULLNAME_CAPACITY];
- status = U_ZERO_ERROR;
- uloc_toLanguageTag(
- icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
- if (U_SUCCESS(status)) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
- NONE,
- kNonStrictMode);
- } else {
- // This would never happen, since we got the locale from ICU.
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
- NONE,
- kNonStrictMode);
- }
-}
-
-
-icu::Collator* CreateICUCollator(
- Isolate* isolate,
- const icu::Locale& icu_locale,
- Handle<JSObject> options) {
- // Make collator from options.
- icu::Collator* collator = NULL;
- UErrorCode status = U_ZERO_ERROR;
- collator = icu::Collator::createInstance(icu_locale, status);
-
- if (U_FAILURE(status)) {
- delete collator;
- return NULL;
- }
-
- // Set flags first, and then override them with sensitivity if necessary.
- bool numeric;
- if (ExtractBooleanSetting(isolate, options, "numeric", &numeric)) {
- collator->setAttribute(
- UCOL_NUMERIC_COLLATION, numeric ? UCOL_ON : UCOL_OFF, status);
- }
-
- // Normalization is always on, by the spec. We are free to optimize
- // if the strings are already normalized (but we don't have a way to tell
- // that right now).
- collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
-
- icu::UnicodeString case_first;
- if (ExtractStringSetting(isolate, options, "caseFirst", &case_first)) {
- if (case_first == UNICODE_STRING_SIMPLE("upper")) {
- collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
- } else if (case_first == UNICODE_STRING_SIMPLE("lower")) {
- collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
- } else {
- // Default (false/off).
- collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
- }
- }
-
- icu::UnicodeString sensitivity;
- if (ExtractStringSetting(isolate, options, "sensitivity", &sensitivity)) {
- if (sensitivity == UNICODE_STRING_SIMPLE("base")) {
- collator->setStrength(icu::Collator::PRIMARY);
- } else if (sensitivity == UNICODE_STRING_SIMPLE("accent")) {
- collator->setStrength(icu::Collator::SECONDARY);
- } else if (sensitivity == UNICODE_STRING_SIMPLE("case")) {
- collator->setStrength(icu::Collator::PRIMARY);
- collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status);
- } else {
- // variant (default)
- collator->setStrength(icu::Collator::TERTIARY);
- }
- }
-
- bool ignore;
- if (ExtractBooleanSetting(isolate, options, "ignorePunctuation", &ignore)) {
- if (ignore) {
- collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
- }
- }
-
- return collator;
-}
-
-
-void SetResolvedCollatorSettings(Isolate* isolate,
- const icu::Locale& icu_locale,
- icu::Collator* collator,
- Handle<JSObject> resolved) {
- UErrorCode status = U_ZERO_ERROR;
-
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("numeric")),
- isolate->factory()->ToBoolean(
- collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON),
- NONE,
- kNonStrictMode);
-
- switch (collator->getAttribute(UCOL_CASE_FIRST, status)) {
- case UCOL_LOWER_FIRST:
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
- isolate->factory()->NewStringFromAscii(CStrVector("lower")),
- NONE,
- kNonStrictMode);
- break;
- case UCOL_UPPER_FIRST:
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
- isolate->factory()->NewStringFromAscii(CStrVector("upper")),
- NONE,
- kNonStrictMode);
- break;
- default:
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
- isolate->factory()->NewStringFromAscii(CStrVector("false")),
- NONE,
- kNonStrictMode);
- }
-
- switch (collator->getAttribute(UCOL_STRENGTH, status)) {
- case UCOL_PRIMARY: {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("primary")),
- NONE,
- kNonStrictMode);
-
- // case level: true + s1 -> case, s1 -> base.
- if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("case")),
- NONE,
- kNonStrictMode);
- } else {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("base")),
- NONE,
- kNonStrictMode);
- }
- break;
- }
- case UCOL_SECONDARY:
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("secondary")),
- NONE,
- kNonStrictMode);
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("accent")),
- NONE,
- kNonStrictMode);
- break;
- case UCOL_TERTIARY:
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("tertiary")),
- NONE,
- kNonStrictMode);
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("variant")),
- NONE,
- kNonStrictMode);
- break;
- case UCOL_QUATERNARY:
- // We shouldn't get quaternary and identical from ICU, but if we do
- // put them into variant.
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("quaternary")),
- NONE,
- kNonStrictMode);
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("variant")),
- NONE,
- kNonStrictMode);
- break;
- default:
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("strength")),
- isolate->factory()->NewStringFromAscii(CStrVector("identical")),
- NONE,
- kNonStrictMode);
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
- isolate->factory()->NewStringFromAscii(CStrVector("variant")),
- NONE,
- kNonStrictMode);
- }
-
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("ignorePunctuation")),
- isolate->factory()->ToBoolean(collator->getAttribute(
- UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED),
- NONE,
- kNonStrictMode);
-
- // Set the locale
- char result[ULOC_FULLNAME_CAPACITY];
- status = U_ZERO_ERROR;
- uloc_toLanguageTag(
- icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
- if (U_SUCCESS(status)) {
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
- NONE,
- kNonStrictMode);
- } else {
- // This would never happen, since we got the locale from ICU.
- JSObject::SetProperty(
- resolved,
- isolate->factory()->NewStringFromAscii(CStrVector("locale")),
- isolate->factory()->NewStringFromAscii(CStrVector("und")),
- NONE,
- kNonStrictMode);
- }
-}
-
-} // namespace
-
-
-// static
-Handle<ObjectTemplateInfo> I18N::GetTemplate(Isolate* isolate) {
- return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
-}
-
-
-// static
-Handle<ObjectTemplateInfo> I18N::GetTemplate2(Isolate* isolate) {
- return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
-}
-
-
-// static
-icu::SimpleDateFormat* DateFormat::InitializeDateTimeFormat(
- Isolate* isolate,
- Handle<String> locale,
- Handle<JSObject> options,
- Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
-
- icu::SimpleDateFormat* date_format = CreateICUDateFormat(
- isolate, icu_locale, options);
- if (!date_format) {
- // Remove extensions and try again.
- icu::Locale no_extension_locale(icu_locale.getBaseName());
- date_format = CreateICUDateFormat(isolate, no_extension_locale, options);
-
- // Set resolved settings (pattern, numbering system, calendar).
- SetResolvedDateSettings(
- isolate, no_extension_locale, date_format, resolved);
- } else {
- SetResolvedDateSettings(isolate, icu_locale, date_format, resolved);
- }
-
- return date_format;
-}
-
-
-icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
- Isolate* isolate,
- Handle<JSObject> obj) {
- Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("dateFormat"));
- if (obj->HasLocalProperty(*key)) {
- return reinterpret_cast<icu::SimpleDateFormat*>(
- obj->GetInternalField(0));
- }
-
- return NULL;
-}
-
-
-void DateFormat::DeleteDateFormat(v8::Isolate* isolate,
- Persistent<v8::Object>* object,
- void* param) {
- // First delete the hidden C++ object.
- delete reinterpret_cast<icu::SimpleDateFormat*>(Handle<JSObject>::cast(
- v8::Utils::OpenPersistent(object))->GetInternalField(0));
-
- // Then dispose of the persistent handle to JS object.
- object->Dispose(isolate);
-}
-
-
-icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
- Isolate* isolate,
- Handle<String> locale,
- Handle<JSObject> options,
- Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
-
- icu::DecimalFormat* number_format =
- CreateICUNumberFormat(isolate, icu_locale, options);
- if (!number_format) {
- // Remove extensions and try again.
- icu::Locale no_extension_locale(icu_locale.getBaseName());
- number_format = CreateICUNumberFormat(
- isolate, no_extension_locale, options);
-
- // Set resolved settings (pattern, numbering system).
- SetResolvedNumberSettings(
- isolate, no_extension_locale, number_format, resolved);
- } else {
- SetResolvedNumberSettings(isolate, icu_locale, number_format, resolved);
- }
-
- return number_format;
-}
-
-
-icu::DecimalFormat* NumberFormat::UnpackNumberFormat(
- Isolate* isolate,
- Handle<JSObject> obj) {
- Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("numberFormat"));
- if (obj->HasLocalProperty(*key)) {
- return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
- }
-
- return NULL;
-}
-
-
-void NumberFormat::DeleteNumberFormat(v8::Isolate* isolate,
- Persistent<v8::Object>* object,
- void* param) {
- // First delete the hidden C++ object.
- delete reinterpret_cast<icu::DecimalFormat*>(Handle<JSObject>::cast(
- v8::Utils::OpenPersistent(object))->GetInternalField(0));
-
- // Then dispose of the persistent handle to JS object.
- object->Dispose(isolate);
-}
-
-
-icu::Collator* Collator::InitializeCollator(
- Isolate* isolate,
- Handle<String> locale,
- Handle<JSObject> options,
- Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
-
- icu::Collator* collator = CreateICUCollator(isolate, icu_locale, options);
- if (!collator) {
- // Remove extensions and try again.
- icu::Locale no_extension_locale(icu_locale.getBaseName());
- collator = CreateICUCollator(isolate, no_extension_locale, options);
-
- // Set resolved settings (pattern, numbering system).
- SetResolvedCollatorSettings(
- isolate, no_extension_locale, collator, resolved);
- } else {
- SetResolvedCollatorSettings(isolate, icu_locale, collator, resolved);
- }
-
- return collator;
-}
-
-
-icu::Collator* Collator::UnpackCollator(Isolate* isolate,
- Handle<JSObject> obj) {
- Handle<String> key =
- isolate->factory()->NewStringFromAscii(CStrVector("collator"));
- if (obj->HasLocalProperty(*key)) {
- return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
- }
-
- return NULL;
-}
-
-
-void Collator::DeleteCollator(v8::Isolate* isolate,
- Persistent<v8::Object>* object,
- void* param) {
- // First delete the hidden C++ object.
- delete reinterpret_cast<icu::Collator*>(Handle<JSObject>::cast(
- v8::Utils::OpenPersistent(object))->GetInternalField(0));
-
- // Then dispose of the persistent handle to JS object.
- object->Dispose(isolate);
-}
-
-} } // namespace v8::internal
diff --git a/chromium/v8/src/i18n.h b/chromium/v8/src/i18n.h
deleted file mode 100644
index 5825ab6c6c7..00000000000
--- a/chromium/v8/src/i18n.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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.
-// limitations under the License.
-
-#ifndef V8_I18N_H_
-#define V8_I18N_H_
-
-#include "unicode/uversion.h"
-#include "v8.h"
-
-namespace U_ICU_NAMESPACE {
-class Collator;
-class DecimalFormat;
-class SimpleDateFormat;
-}
-
-namespace v8 {
-namespace internal {
-
-class I18N {
- public:
- // Creates an ObjectTemplate with one internal field.
- static Handle<ObjectTemplateInfo> GetTemplate(Isolate* isolate);
-
- // Creates an ObjectTemplate with two internal fields.
- static Handle<ObjectTemplateInfo> GetTemplate2(Isolate* isolate);
-
- private:
- I18N();
-};
-
-
-class DateFormat {
- public:
- // Create a formatter for the specificied locale and options. Returns the
- // resolved settings for the locale / options.
- static icu::SimpleDateFormat* InitializeDateTimeFormat(
- Isolate* isolate,
- Handle<String> locale,
- Handle<JSObject> options,
- Handle<JSObject> resolved);
-
- // Unpacks date format object from corresponding JavaScript object.
- static icu::SimpleDateFormat* UnpackDateFormat(Isolate* isolate,
- Handle<JSObject> obj);
-
- // Release memory we allocated for the DateFormat once the JS object that
- // holds the pointer gets garbage collected.
- static void DeleteDateFormat(v8::Isolate* isolate,
- Persistent<v8::Object>* object,
- void* param);
- private:
- DateFormat();
-};
-
-
-class NumberFormat {
- public:
- // Create a formatter for the specificied locale and options. Returns the
- // resolved settings for the locale / options.
- static icu::DecimalFormat* InitializeNumberFormat(
- Isolate* isolate,
- Handle<String> locale,
- Handle<JSObject> options,
- Handle<JSObject> resolved);
-
- // Unpacks number format object from corresponding JavaScript object.
- static icu::DecimalFormat* UnpackNumberFormat(Isolate* isolate,
- Handle<JSObject> obj);
-
- // Release memory we allocated for the NumberFormat once the JS object that
- // holds the pointer gets garbage collected.
- static void DeleteNumberFormat(v8::Isolate* isolate,
- Persistent<v8::Object>* object,
- void* param);
- private:
- NumberFormat();
-};
-
-
-class Collator {
- public:
- // Create a collator for the specificied locale and options. Returns the
- // resolved settings for the locale / options.
- static icu::Collator* InitializeCollator(
- Isolate* isolate,
- Handle<String> locale,
- Handle<JSObject> options,
- Handle<JSObject> resolved);
-
- // Unpacks collator object from corresponding JavaScript object.
- static icu::Collator* UnpackCollator(Isolate* isolate, Handle<JSObject> obj);
-
- // Release memory we allocated for the Collator once the JS object that holds
- // the pointer gets garbage collected.
- static void DeleteCollator(v8::Isolate* isolate,
- Persistent<v8::Object>* object,
- void* param);
- private:
- Collator();
-};
-
-} } // namespace v8::internal
-
-#endif // V8_I18N_H_
diff --git a/chromium/v8/src/ia32/assembler-ia32.cc b/chromium/v8/src/ia32/assembler-ia32.cc
index 7bea3730258..e0ae0066552 100644
--- a/chromium/v8/src/ia32/assembler-ia32.cc
+++ b/chromium/v8/src/ia32/assembler-ia32.cc
@@ -1227,10 +1227,6 @@ void Assembler::test_b(Register reg, const Operand& op) {
void Assembler::test(const Operand& op, const Immediate& imm) {
- if (op.is_reg_only()) {
- test(op.reg(), imm);
- return;
- }
EnsureSpace ensure_space(this);
EMIT(0xF7);
emit_operand(eax, op);
diff --git a/chromium/v8/src/ia32/builtins-ia32.cc b/chromium/v8/src/ia32/builtins-ia32.cc
index 59124eab757..b90a17f6c38 100644
--- a/chromium/v8/src/ia32/builtins-ia32.cc
+++ b/chromium/v8/src/ia32/builtins-ia32.cc
@@ -241,7 +241,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (FLAG_debug_code) {
__ cmp(esi, edi);
__ Assert(less_equal,
- kUnexpectedNumberOfPreAllocatedPropertyFields);
+ "Unexpected number of pre-allocated property fields.");
}
__ InitializeFieldsWithFiller(ecx, esi, edx);
__ mov(edx, factory->one_pointer_filler_map());
@@ -272,7 +272,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ sub(edx, ecx);
// Done if no extra properties are to be allocated.
__ j(zero, &allocated);
- __ Assert(positive, kPropertyAllocationCountFailed);
+ __ Assert(positive, "Property allocation count failed.");
// Scale the number of elements by pointer size and add the header for
// FixedArrays to the start of the next object calculation from above.
@@ -654,7 +654,7 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
__ ret(2 * kPointerSize); // Remove state, eax.
__ bind(&not_tos_eax);
- __ Abort(kNoCasesLeft);
+ __ Abort("no cases left");
}
@@ -1033,9 +1033,9 @@ void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
__ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ test(ebx, Immediate(kSmiTagMask));
- __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
+ __ Assert(not_zero, "Unexpected initial map for InternalArray function");
__ CmpObjectType(ebx, MAP_TYPE, ecx);
- __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
+ __ Assert(equal, "Unexpected initial map for InternalArray function");
}
// Run the native code for the InternalArray function called as a normal
@@ -1062,9 +1062,9 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ test(ebx, Immediate(kSmiTagMask));
- __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(not_zero, "Unexpected initial map for Array function");
__ CmpObjectType(ebx, MAP_TYPE, ecx);
- __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(equal, "Unexpected initial map for Array function");
}
// Run the native code for the Array function called as a normal function.
@@ -1092,7 +1092,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx);
__ cmp(edi, ecx);
- __ Assert(equal, kUnexpectedStringFunction);
+ __ Assert(equal, "Unexpected String function");
}
// Load the first argument into eax and get rid of the rest
@@ -1137,9 +1137,9 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset),
JSValue::kSize >> kPointerSizeLog2);
- __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
+ __ Assert(equal, "Unexpected string wrapper instance size");
__ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0);
- __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
+ __ Assert(equal, "Unexpected unused properties of string wrapper");
}
__ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
diff --git a/chromium/v8/src/ia32/code-stubs-ia32.cc b/chromium/v8/src/ia32/code-stubs-ia32.cc
index 12cc499a777..5789f49216f 100644
--- a/chromium/v8/src/ia32/code-stubs-ia32.cc
+++ b/chromium/v8/src/ia32/code-stubs-ia32.cc
@@ -250,6 +250,17 @@ void ToBooleanStub::InitializeInterfaceDescriptor(
}
+void UnaryOpStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { eax };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
void StoreGlobalStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -500,8 +511,9 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
Label after_sentinel;
__ JumpIfNotSmi(ecx, &after_sentinel, Label::kNear);
if (FLAG_debug_code) {
+ const char* message = "Expected 0 as a Smi sentinel";
__ cmp(ecx, 0);
- __ Assert(equal, kExpected0AsASmiSentinel);
+ __ Assert(equal, message);
}
__ mov(ecx, GlobalObjectOperand());
__ mov(ecx, FieldOperand(ecx, GlobalObject::kNativeContextOffset));
@@ -3457,9 +3469,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
if (FLAG_debug_code) {
__ test(ecx, Immediate(kSmiTagMask));
- __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected);
+ __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected");
__ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
- __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
+ __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
}
// ecx: RegExp data (FixedArray)
@@ -3819,7 +3831,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ test_b(ebx, kIsIndirectStringMask);
- __ Assert(zero, kExternalStringExpectedButNotFound);
+ __ Assert(zero, "external string expected, but not found");
}
__ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
// Move the pointer so that offset-wise, it looks like a sequential string.
@@ -3956,7 +3968,11 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
Register scratch = scratch2;
// Load the number string cache.
- __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
+ ExternalReference roots_array_start =
+ ExternalReference::roots_array_start(masm->isolate());
+ __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex));
+ __ mov(number_string_cache,
+ Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
__ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
@@ -4310,7 +4326,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
edi);
}
#ifdef DEBUG
- __ Abort(kUnexpectedFallThroughFromStringComparison);
+ __ Abort("Unexpected fall-through from string comparison");
#endif
__ bind(&check_unequal_objects);
@@ -5006,6 +5022,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d);
static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8);
+ ExternalReference roots_array_start =
+ ExternalReference::roots_array_start(masm->isolate());
+
ASSERT_EQ(object.code(), InstanceofStub::left().code());
ASSERT_EQ(function.code(), InstanceofStub::right().code());
@@ -5025,11 +5044,18 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
if (!HasCallSiteInlineCheck()) {
// Look up the function and the map in the instanceof cache.
Label miss;
- __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
+ __ cmp(function, Operand::StaticArray(scratch,
+ times_pointer_size,
+ roots_array_start));
__ j(not_equal, &miss, Label::kNear);
- __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex);
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
+ __ cmp(map, Operand::StaticArray(
+ scratch, times_pointer_size, roots_array_start));
__ j(not_equal, &miss, Label::kNear);
- __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex);
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
+ __ mov(eax, Operand::StaticArray(
+ scratch, times_pointer_size, roots_array_start));
__ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
__ bind(&miss);
}
@@ -5044,8 +5070,12 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
// Update the global instanceof or call site inlined cache with the current
// map and function. The cached answer will be set when it is known below.
if (!HasCallSiteInlineCheck()) {
- __ StoreRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex);
- __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
+ __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
+ map);
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
+ __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
+ function);
} else {
// The constants for the code patching are based on no push instructions
// at the call site.
@@ -5055,9 +5085,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ sub(scratch, Operand(esp, 1 * kPointerSize));
if (FLAG_debug_code) {
__ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)");
__ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp2);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)");
}
__ mov(scratch, Operand(scratch, kDeltaToCmpImmediate));
__ mov(Operand(scratch, 0), map);
@@ -5079,8 +5109,10 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ bind(&is_instance);
if (!HasCallSiteInlineCheck()) {
- __ mov(eax, Immediate(0));
- __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
+ __ Set(eax, Immediate(0));
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
+ __ mov(Operand::StaticArray(scratch,
+ times_pointer_size, roots_array_start), eax);
} else {
// Get return address and delta to inlined map check.
__ mov(eax, factory->true_value());
@@ -5088,7 +5120,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ sub(scratch, Operand(esp, 1 * kPointerSize));
if (FLAG_debug_code) {
__ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
}
__ mov(Operand(scratch, kDeltaToMovImmediate), eax);
if (!ReturnTrueFalseObject()) {
@@ -5099,8 +5131,10 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ bind(&is_not_instance);
if (!HasCallSiteInlineCheck()) {
- __ mov(eax, Immediate(Smi::FromInt(1)));
- __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
+ __ Set(eax, Immediate(Smi::FromInt(1)));
+ __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
+ __ mov(Operand::StaticArray(
+ scratch, times_pointer_size, roots_array_start), eax);
} else {
// Get return address and delta to inlined map check.
__ mov(eax, factory->false_value());
@@ -5108,7 +5142,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ sub(scratch, Operand(esp, 1 * kPointerSize));
if (FLAG_debug_code) {
__ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
}
__ mov(Operand(scratch, kDeltaToMovImmediate), eax);
if (!ReturnTrueFalseObject()) {
@@ -5221,7 +5255,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharCodeAtGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough to CharCodeAt slow case");
// Index is not a smi.
__ bind(&index_not_smi_);
@@ -5271,7 +5305,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough from CharCodeAt slow case");
}
@@ -5306,7 +5340,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough to CharFromCode slow case");
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
@@ -5318,7 +5352,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough from CharFromCode slow case");
}
@@ -5853,7 +5887,11 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
// Load the string table.
Register string_table = c2;
- __ LoadRoot(string_table, Heap::kStringTableRootIndex);
+ ExternalReference roots_array_start =
+ ExternalReference::roots_array_start(masm->isolate());
+ __ mov(scratch, Immediate(Heap::kStringTableRootIndex));
+ __ mov(string_table,
+ Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
// Calculate capacity mask from the string table capacity.
Register mask = scratch2;
@@ -5941,7 +5979,12 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
Register scratch) {
// hash = (seed + character) + ((seed + character) << 10);
if (Serializer::enabled()) {
- __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
+ ExternalReference roots_array_start =
+ ExternalReference::roots_array_start(masm->isolate());
+ __ mov(scratch, Immediate(Heap::kHashSeedRootIndex));
+ __ mov(scratch, Operand::StaticArray(scratch,
+ times_pointer_size,
+ roots_array_start));
__ SmiUntag(scratch);
__ add(scratch, character);
__ mov(hash, scratch);
@@ -7439,7 +7482,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -7502,7 +7545,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -7567,9 +7610,9 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ test(ecx, Immediate(kSmiTagMask));
- __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(not_zero, "Unexpected initial map for Array function");
__ CmpObjectType(ecx, MAP_TYPE, ecx);
- __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(equal, "Unexpected initial map for Array function");
// We should either have undefined in ebx or a valid cell
Label okay_here;
@@ -7577,7 +7620,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ cmp(ebx, Immediate(undefined_sentinel));
__ j(equal, &okay_here);
__ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
- __ Assert(equal, kExpectedPropertyCellInRegisterEbx);
+ __ Assert(equal, "Expected property cell in register ebx");
__ bind(&okay_here);
}
@@ -7681,9 +7724,9 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
__ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ test(ecx, Immediate(kSmiTagMask));
- __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(not_zero, "Unexpected initial map for Array function");
__ CmpObjectType(ecx, MAP_TYPE, ecx);
- __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
+ __ Assert(equal, "Unexpected initial map for Array function");
}
// Figure out the right elements kind
@@ -7702,7 +7745,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
__ j(equal, &done);
__ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS));
__ Assert(equal,
- kInvalidElementsKindForInternalArrayOrInternalPackedArray);
+ "Invalid ElementsKind for InternalArray or InternalPackedArray");
__ bind(&done);
}
diff --git a/chromium/v8/src/ia32/codegen-ia32.cc b/chromium/v8/src/ia32/codegen-ia32.cc
index 28b0f4ad82f..f488718dc6d 100644
--- a/chromium/v8/src/ia32/codegen-ia32.cc
+++ b/chromium/v8/src/ia32/codegen-ia32.cc
@@ -779,7 +779,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
if (FLAG_debug_code) {
__ cmp(ebx, masm->isolate()->factory()->the_hole_value());
- __ Assert(equal, kObjectFoundInSmiOnlyArray);
+ __ Assert(equal, "object found in smi-only array");
}
if (CpuFeatures::IsSupported(SSE2)) {
@@ -1011,7 +1011,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ test(result, Immediate(kIsIndirectStringMask));
- __ Assert(zero, kExternalStringExpectedButNotFound);
+ __ Assert(zero, "external string expected, but not found");
}
// Rule out short external strings.
STATIC_CHECK(kShortExternalStringTag != 0);
diff --git a/chromium/v8/src/ia32/debug-ia32.cc b/chromium/v8/src/ia32/debug-ia32.cc
index fd703dcc0c7..68199f905b5 100644
--- a/chromium/v8/src/ia32/debug-ia32.cc
+++ b/chromium/v8/src/ia32/debug-ia32.cc
@@ -128,7 +128,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
if ((non_object_regs & (1 << r)) != 0) {
if (FLAG_debug_code) {
__ test(reg, Immediate(0xc0000000));
- __ Assert(zero, kUnableToEncodeValueAsSmi);
+ __ Assert(zero, "Unable to encode value as smi");
}
__ SmiTag(reg);
__ push(reg);
diff --git a/chromium/v8/src/ia32/deoptimizer-ia32.cc b/chromium/v8/src/ia32/deoptimizer-ia32.cc
index a9bd8c50b72..48968064aa3 100644
--- a/chromium/v8/src/ia32/deoptimizer-ia32.cc
+++ b/chromium/v8/src/ia32/deoptimizer-ia32.cc
@@ -625,7 +625,7 @@ void Deoptimizer::EntryGenerator::Generate() {
__ pop(ecx);
if (FLAG_debug_code) {
__ cmp(ecx, Immediate(kAlignmentZapValue));
- __ Assert(equal, kAlignmentMarkerExpected);
+ __ Assert(equal, "alignment marker expected");
}
__ bind(&no_padding);
} else {
diff --git a/chromium/v8/src/ia32/full-codegen-ia32.cc b/chromium/v8/src/ia32/full-codegen-ia32.cc
index f08a269e85b..8f11acc1bec 100644
--- a/chromium/v8/src/ia32/full-codegen-ia32.cc
+++ b/chromium/v8/src/ia32/full-codegen-ia32.cc
@@ -745,9 +745,9 @@ void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
// Check that we're not inside a with or catch context.
__ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
__ cmp(ebx, isolate()->factory()->with_context_map());
- __ Check(not_equal, kDeclarationInWithContext);
+ __ Check(not_equal, "Declaration in with context.");
__ cmp(ebx, isolate()->factory()->catch_context_map());
- __ Check(not_equal, kDeclarationInCatchContext);
+ __ Check(not_equal, "Declaration in catch context.");
}
}
@@ -2169,7 +2169,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
__ Push(Smi::FromInt(resume_mode));
__ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
// Not reached: the runtime call returns elsewhere.
- __ Abort(kGeneratorFailedToResume);
+ __ Abort("Generator failed to resume.");
// Throw error if we attempt to operate on a running generator.
__ bind(&wrong_state);
@@ -2468,7 +2468,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Check for an uninitialized let binding.
__ mov(edx, location);
__ cmp(edx, isolate()->factory()->the_hole_value());
- __ Check(equal, kLetBindingReInitialization);
+ __ Check(equal, "Let binding re-initialization.");
}
// Perform the assignment.
__ mov(location, eax);
@@ -3430,15 +3430,15 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
Register value,
uint32_t encoding_mask) {
__ test(index, Immediate(kSmiTagMask));
- __ Check(zero, kNonSmiIndex);
+ __ Check(zero, "Non-smi index");
__ test(value, Immediate(kSmiTagMask));
- __ Check(zero, kNonSmiValue);
+ __ Check(zero, "Non-smi value");
__ cmp(index, FieldOperand(string, String::kLengthOffset));
- __ Check(less, kIndexIsTooLarge);
+ __ Check(less, "Index is too large");
__ cmp(index, Immediate(Smi::FromInt(0)));
- __ Check(greater_equal, kIndexIsNegative);
+ __ Check(greater_equal, "Index is negative");
__ push(value);
__ mov(value, FieldOperand(string, HeapObject::kMapOffset));
@@ -3446,7 +3446,7 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
__ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
__ cmp(value, Immediate(encoding_mask));
- __ Check(equal, kUnexpectedStringType);
+ __ Check(equal, "Unexpected string type");
__ pop(value);
}
@@ -3818,7 +3818,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
Handle<FixedArray> jsfunction_result_caches(
isolate()->native_context()->jsfunction_result_caches());
if (jsfunction_result_caches->length() <= cache_id) {
- __ Abort(kAttemptToUseUndefinedCache);
+ __ Abort("Attempt to use undefined cache.");
__ mov(eax, isolate()->factory()->undefined_value());
context()->Plug(eax);
return;
@@ -4000,7 +4000,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// scratch, string_length, elements.
if (generate_debug_code_) {
__ cmp(index, array_length);
- __ Assert(less, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
+ __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
}
__ bind(&loop);
__ mov(string, FieldOperand(elements,
@@ -4347,12 +4347,34 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
+ case Token::SUB:
+ EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
+ break;
+
+ case Token::BIT_NOT:
+ EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
+ break;
+
default:
UNREACHABLE();
}
}
+void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
+ const char* comment) {
+ Comment cmt(masm_, comment);
+ UnaryOpStub stub(expr->op());
+ // UnaryOpStub expects the argument to be in the
+ // accumulator register eax.
+ VisitForAccumulatorValue(expr->expression());
+ SetSourcePosition(expr->position());
+ CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
+ expr->UnaryOperationFeedbackId());
+ context()->Plug(eax);
+}
+
+
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
diff --git a/chromium/v8/src/ia32/ic-ia32.cc b/chromium/v8/src/ia32/ic-ia32.cc
index 1e0f14e7687..bf0c80b2b46 100644
--- a/chromium/v8/src/ia32/ic-ia32.cc
+++ b/chromium/v8/src/ia32/ic-ia32.cc
@@ -483,7 +483,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// based on 32 bits of the map pointer and the string hash.
if (FLAG_debug_code) {
__ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset));
- __ Check(equal, kMapIsNoLongerInEax);
+ __ Check(equal, "Map is no longer in eax.");
}
__ mov(ebx, eax); // Keep the map around for later.
__ shr(eax, KeyedLookupCache::kMapHashShift);
diff --git a/chromium/v8/src/ia32/lithium-codegen-ia32.cc b/chromium/v8/src/ia32/lithium-codegen-ia32.cc
index 19c553bfa51..7a601cf39bc 100644
--- a/chromium/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/chromium/v8/src/ia32/lithium-codegen-ia32.cc
@@ -113,7 +113,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
}
-void LCodeGen::Abort(BailoutReason reason) {
+void LCodeGen::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -220,7 +220,7 @@ bool LCodeGen::GeneratePrologue() {
dynamic_frame_alignment_ &&
FLAG_debug_code) {
__ test(esp, Immediate(kPointerSize));
- __ Assert(zero, kFrameIsExpectedToBeAligned);
+ __ Assert(zero, "frame is expected to be aligned");
}
// Reserve space for the stack slots needed by the code.
@@ -355,8 +355,6 @@ bool LCodeGen::GenerateBody() {
if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr);
- RecordAndUpdatePosition(instr->position());
-
instr->CompileToNative(this);
if (!CpuFeatures::IsSupported(SSE2)) {
@@ -424,10 +422,6 @@ bool LCodeGen::GenerateDeferredCode() {
if (deferred_.length() > 0) {
for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
LDeferredCode* code = deferred_[i];
-
- int pos = instructions_->at(code->instruction_index())->position();
- RecordAndUpdatePosition(pos);
-
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",
code->instruction_index(),
@@ -769,57 +763,37 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
UNREACHABLE();
}
- int object_index = 0;
- int dematerialized_index = 0;
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
- AddToTranslation(environment,
- translation,
+
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
+ AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- &object_index,
- &dematerialized_index);
+ environment->HasUint32ValueAt(i));
}
}
-void LCodeGen::AddToTranslation(LEnvironment* environment,
- Translation* translation,
+void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer) {
- if (op == LEnvironment::materialization_marker()) {
- int object_index = (*object_index_pointer)++;
- if (environment->ObjectIsDuplicateAt(object_index)) {
- int dupe_of = environment->ObjectDuplicateOfAt(object_index);
- translation->DuplicateObject(dupe_of);
- return;
- }
- int object_length = environment->ObjectLengthAt(object_index);
- if (environment->ObjectIsArgumentsAt(object_index)) {
- translation->BeginArgumentsObject(object_length);
- } else {
- translation->BeginCapturedObject(object_length);
- }
- int dematerialized_index = *dematerialized_index_pointer;
- int env_offset = environment->translation_size() + dematerialized_index;
- *dematerialized_index_pointer += object_length;
- for (int i = 0; i < object_length; ++i) {
- LOperand* value = environment->values()->at(env_offset + i);
- AddToTranslation(environment,
- translation,
- value,
- environment->HasTaggedValueAt(env_offset + i),
- environment->HasUint32ValueAt(env_offset + i),
- object_index_pointer,
- dematerialized_index_pointer);
- }
- return;
- }
-
+ bool is_uint32) {
if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
@@ -908,7 +882,7 @@ void LCodeGen::LoadContextFromDeferred(LOperand* context) {
} else if (context->IsConstantOperand()) {
HConstant* constant =
chunk_->LookupConstant(LConstantOperand::cast(context));
- __ LoadObject(esi, Handle<Object>::cast(constant->handle()));
+ __ LoadHeapObject(esi, Handle<Context>::cast(constant->handle()));
} else {
UNREACHABLE();
}
@@ -974,7 +948,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
Address entry =
Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
if (entry == NULL) {
- Abort(kBailoutWasNotPrepared);
+ Abort("bailout was not prepared");
return;
}
@@ -1010,7 +984,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
__ bind(&done);
}
- if (info()->ShouldTrapOnDeopt()) {
+ if (FLAG_trap_on_deopt && info()->IsOptimizing()) {
Label done;
if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
__ int3();
@@ -1194,14 +1168,6 @@ void LCodeGen::RecordPosition(int position) {
}
-void LCodeGen::RecordAndUpdatePosition(int position) {
- if (position >= 0 && position != old_position_) {
- masm()->positions_recorder()->RecordPosition(position);
- old_position_ = position;
- }
-}
-
-
static const char* LabelType(LLabel* label) {
if (label->is_loop_header()) return " (loop header)";
if (label->is_osr_entry()) return " (OSR entry)";
@@ -1713,9 +1679,8 @@ void LCodeGen::DoBitI(LBitI* instr) {
ASSERT(left->IsRegister());
if (right->IsConstantOperand()) {
- int32_t right_operand =
- ToRepresentation(LConstantOperand::cast(right),
- instr->hydrogen()->representation());
+ int right_operand = ToRepresentation(LConstantOperand::cast(right),
+ instr->hydrogen()->representation());
switch (instr->op()) {
case Token::BIT_AND:
__ and_(ToRegister(left), right_operand);
@@ -1724,11 +1689,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
__ or_(ToRegister(left), right_operand);
break;
case Token::BIT_XOR:
- if (right_operand == int32_t(~0)) {
- __ not_(ToRegister(left));
- } else {
- __ xor_(ToRegister(left), right_operand);
- }
+ __ xor_(ToRegister(left), right_operand);
break;
default:
UNREACHABLE();
@@ -2015,7 +1976,7 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
__ cmp(value, Immediate(encoding == String::ONE_BYTE_ENCODING
? one_byte_seq_type : two_byte_seq_type));
- __ Check(equal, kUnexpectedStringType);
+ __ Check(equal, "Unexpected string type");
__ pop(value);
}
@@ -2029,6 +1990,13 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
}
+void LCodeGen::DoBitNotI(LBitNotI* instr) {
+ LOperand* input = instr->value();
+ ASSERT(input->Equals(instr->result()));
+ __ not_(ToRegister(input));
+}
+
+
void LCodeGen::DoThrow(LThrow* instr) {
__ push(ToOperand(instr->value()));
ASSERT(ToRegister(instr->context()).is(esi));
@@ -2233,17 +2201,6 @@ void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
}
-template<class InstrType>
-void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
- int false_block = instr->FalseDestination(chunk_);
- if (cc == no_condition) {
- __ jmp(chunk_->GetAssemblyLabel(false_block));
- } else {
- __ j(cc, chunk_->GetAssemblyLabel(false_block));
- }
-}
-
-
void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
Representation r = instr->hydrogen()->value()->representation();
if (r.IsSmiOrInteger32() || r.IsDouble()) {
@@ -2494,51 +2451,6 @@ void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
}
-void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
- if (instr->hydrogen()->representation().IsTagged()) {
- Register input_reg = ToRegister(instr->object());
- __ cmp(input_reg, factory()->the_hole_value());
- EmitBranch(instr, equal);
- return;
- }
-
- bool use_sse2 = CpuFeatures::IsSupported(SSE2);
- if (use_sse2) {
- CpuFeatureScope scope(masm(), SSE2);
- XMMRegister input_reg = ToDoubleRegister(instr->object());
- __ ucomisd(input_reg, input_reg);
- EmitFalseBranch(instr, parity_odd);
- } else {
- // Put the value to the top of stack
- X87Register src = ToX87Register(instr->object());
- X87LoadForUsage(src);
- __ fld(0);
- __ fld(0);
- __ FCmp();
- Label ok;
- __ j(parity_even, &ok);
- __ fstp(0);
- EmitFalseBranch(instr, no_condition);
- __ bind(&ok);
- }
-
-
- __ sub(esp, Immediate(kDoubleSize));
- if (use_sse2) {
- CpuFeatureScope scope(masm(), SSE2);
- XMMRegister input_reg = ToDoubleRegister(instr->object());
- __ movdbl(MemOperand(esp, 0), input_reg);
- } else {
- __ fstp_d(MemOperand(esp, 0));
- }
-
- __ add(esp, Immediate(kDoubleSize));
- int offset = sizeof(kHoleNanUpper32);
- __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
- EmitBranch(instr, equal);
-}
-
-
Condition LCodeGen::EmitIsObject(Register input,
Register temp1,
Label* is_not_object,
@@ -2951,7 +2863,7 @@ void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
__ cmp(Operand(esp,
(parameter_count + extra_value_count) * kPointerSize),
Immediate(kAlignmentZapValue));
- __ Assert(equal, kExpectedAlignmentMarker);
+ __ Assert(equal, "expected alignment marker");
}
__ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
} else {
@@ -2964,7 +2876,7 @@ void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
__ cmp(Operand(esp, reg, times_pointer_size,
extra_value_count * kPointerSize),
Immediate(kAlignmentZapValue));
- __ Assert(equal, kExpectedAlignmentMarker);
+ __ Assert(equal, "expected alignment marker");
}
// emit code to restore stack based on instr->parameter_count()
@@ -3178,6 +3090,47 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
}
+void LCodeGen::EmitLoadFieldOrConstant(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env) {
+ LookupResult lookup(isolate());
+ type->LookupDescriptor(NULL, *name, &lookup);
+ ASSERT(lookup.IsFound() || lookup.IsCacheable());
+ if (lookup.IsField()) {
+ int index = lookup.GetLocalFieldIndexFromMap(*type);
+ int offset = index * kPointerSize;
+ if (index < 0) {
+ // Negative property indices are in-object properties, indexed
+ // from the end of the fixed part of the object.
+ __ mov(result, FieldOperand(object, offset + type->instance_size()));
+ } else {
+ // Non-negative property indices are in the properties array.
+ __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
+ __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
+ }
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
+ } else {
+ // Negative lookup.
+ // Check prototypes.
+ Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
+ Heap* heap = type->GetHeap();
+ while (*current != heap->null_value()) {
+ __ LoadHeapObject(result, current);
+ __ cmp(FieldOperand(result, HeapObject::kMapOffset),
+ Handle<Map>(current->map()));
+ DeoptimizeIf(not_equal, env);
+ current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
+ }
+ __ mov(result, factory()->undefined_value());
+ }
+}
+
+
void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
ASSERT(!operand->IsDoubleRegister());
if (operand->IsConstantOperand()) {
@@ -3196,6 +3149,68 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
}
+// Check for cases where EmitLoadFieldOrConstantFunction needs to walk the
+// prototype chain, which causes unbounded code generation.
+static bool CompactEmit(SmallMapList* list,
+ Handle<String> name,
+ int i,
+ Isolate* isolate) {
+ Handle<Map> map = list->at(i);
+ LookupResult lookup(isolate);
+ map->LookupDescriptor(NULL, *name, &lookup);
+ return lookup.IsField() || lookup.IsConstant();
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+ Register object = ToRegister(instr->object());
+ Register result = ToRegister(instr->result());
+
+ int map_count = instr->hydrogen()->types()->length();
+ bool need_generic = instr->hydrogen()->need_generic();
+
+ if (map_count == 0 && !need_generic) {
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ Handle<String> name = instr->hydrogen()->name();
+ Label done;
+ bool all_are_compact = true;
+ for (int i = 0; i < map_count; ++i) {
+ if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) {
+ all_are_compact = false;
+ break;
+ }
+ }
+ for (int i = 0; i < map_count; ++i) {
+ bool last = (i == map_count - 1);
+ Handle<Map> map = instr->hydrogen()->types()->at(i);
+ Label check_passed;
+ __ CompareMap(object, map, &check_passed);
+ if (last && !need_generic) {
+ DeoptimizeIf(not_equal, instr->environment());
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
+ } else {
+ Label next;
+ bool compact = all_are_compact ? true :
+ CompactEmit(instr->hydrogen()->types(), name, i, isolate());
+ __ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
+ __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
+ __ bind(&next);
+ }
+ }
+ if (need_generic) {
+ __ mov(ecx, name);
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ CallCode(ic, RelocInfo::CODE_TARGET, instr);
+ }
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
@@ -3432,7 +3447,7 @@ Operand LCodeGen::BuildFastArrayOperand(
if (key->IsConstantOperand()) {
int constant_value = ToInteger32(LConstantOperand::cast(key));
if (constant_value & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big");
}
return Operand(elements_pointer_reg,
((constant_value + additional_index) << shift_size)
@@ -3806,7 +3821,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
__ xorps(scratch, scratch);
__ subsd(scratch, input_reg);
__ pand(input_reg, scratch);
- } else if (r.IsSmiOrInteger32()) {
+ } else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else { // Tagged case.
DeferredMathAbsTaggedHeapNumber* deferred =
@@ -4148,9 +4163,6 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
void LCodeGen::DoMathTan(LMathTan* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
- // Set the context register to a GC-safe fake value. Clobbering it is
- // OK because this instruction is marked as a call.
- __ Set(esi, Immediate(0));
TranscendentalCacheStub stub(TranscendentalCache::TAN,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -4159,9 +4171,6 @@ void LCodeGen::DoMathTan(LMathTan* instr) {
void LCodeGen::DoMathCos(LMathCos* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
- // Set the context register to a GC-safe fake value. Clobbering it is
- // OK because this instruction is marked as a call.
- __ Set(esi, Immediate(0));
TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -4170,9 +4179,6 @@ void LCodeGen::DoMathCos(LMathCos* instr) {
void LCodeGen::DoMathSin(LMathSin* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
- // Set the context register to a GC-safe fake value. Clobbering it is
- // OK because this instruction is marked as a call.
- __ Set(esi, Immediate(0));
TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -5045,6 +5051,13 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
Register reg = ToRegister(instr->result());
+ bool convert_hole = false;
+ HValue* change_input = instr->hydrogen()->value();
+ if (change_input->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(change_input);
+ convert_hole = load->UsesMustHandleHole();
+ }
+
bool use_sse2 = CpuFeatures::IsSupported(SSE2);
if (!use_sse2) {
// Put the value to the top of stack
@@ -5052,6 +5065,54 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
X87LoadForUsage(src);
}
+ Label no_special_nan_handling;
+ Label done;
+ if (convert_hole) {
+ if (use_sse2) {
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToDoubleRegister(instr->value());
+ __ ucomisd(input_reg, input_reg);
+ } else {
+ __ fld(0);
+ __ fld(0);
+ __ FCmp();
+ }
+
+ __ j(parity_odd, &no_special_nan_handling);
+ __ sub(esp, Immediate(kDoubleSize));
+ if (use_sse2) {
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToDoubleRegister(instr->value());
+ __ movdbl(MemOperand(esp, 0), input_reg);
+ } else {
+ __ fld(0);
+ __ fstp_d(MemOperand(esp, 0));
+ }
+ __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
+ Immediate(kHoleNanUpper32));
+ Label canonicalize;
+ __ j(not_equal, &canonicalize);
+ __ add(esp, Immediate(kDoubleSize));
+ __ mov(reg, factory()->the_hole_value());
+ if (!use_sse2) {
+ __ fstp(0);
+ }
+ __ jmp(&done);
+ __ bind(&canonicalize);
+ __ add(esp, Immediate(kDoubleSize));
+ ExternalReference nan =
+ ExternalReference::address_of_canonical_non_hole_nan();
+ if (use_sse2) {
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToDoubleRegister(instr->value());
+ __ movdbl(input_reg, Operand::StaticVariable(nan));
+ } else {
+ __ fstp(0);
+ __ fld_d(Operand::StaticVariable(nan));
+ }
+ }
+
+ __ bind(&no_special_nan_handling);
DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
if (FLAG_inline_new) {
Register tmp = ToRegister(instr->temp());
@@ -5067,6 +5128,7 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
} else {
__ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
}
+ __ bind(&done);
}
@@ -5116,21 +5178,23 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
Register temp_reg,
X87Register res_reg,
- bool can_convert_undefined_to_nan,
+ bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
Label load_smi, done;
X87PrepareToWrite(res_reg);
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
// Heap number map check.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
- if (!can_convert_undefined_to_nan) {
+ if (!allow_undefined_as_nan) {
DeoptimizeIf(not_equal, env);
} else {
Label heap_number, convert;
@@ -5138,6 +5202,10 @@ void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
// Convert undefined (or hole) to NaN.
__ cmp(input_reg, factory()->undefined_value());
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ j(equal, &convert, Label::kNear);
+ __ cmp(input_reg, factory()->the_hole_value());
+ }
DeoptimizeIf(not_equal, env);
__ bind(&convert);
@@ -5184,20 +5252,22 @@ void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
void LCodeGen::EmitNumberUntagD(Register input_reg,
Register temp_reg,
XMMRegister result_reg,
- bool can_convert_undefined_to_nan,
+ bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
Label load_smi, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
// Heap number map check.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
- if (!can_convert_undefined_to_nan) {
+ if (!allow_undefined_as_nan) {
DeoptimizeIf(not_equal, env);
} else {
Label heap_number, convert;
@@ -5205,6 +5275,10 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Convert undefined (and hole) to NaN.
__ cmp(input_reg, factory()->undefined_value());
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ j(equal, &convert, Label::kNear);
+ __ cmp(input_reg, factory()->the_hole_value());
+ }
DeoptimizeIf(not_equal, env);
__ bind(&convert);
@@ -5529,9 +5603,16 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
instr->hydrogen()->deoptimize_on_minus_zero();
Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg;
+ NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
- NumberUntagDMode mode = value->representation().IsSmi()
- ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
+ if (value->representation().IsSmi()) {
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
+ }
+ }
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
@@ -5539,7 +5620,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
EmitNumberUntagD(input_reg,
temp_reg,
result_reg,
- instr->hydrogen()->can_convert_undefined_to_nan(),
+ instr->hydrogen()->allow_undefined_as_nan(),
deoptimize_on_minus_zero,
instr->environment(),
mode);
@@ -5547,7 +5628,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
EmitNumberUntagDNoSSE2(input_reg,
temp_reg,
ToX87Register(instr->result()),
- instr->hydrogen()->can_convert_undefined_to_nan(),
+ instr->hydrogen()->allow_undefined_as_nan(),
deoptimize_on_minus_zero,
instr->environment(),
mode);
@@ -5712,68 +5793,31 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
}
-void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
- {
- PushSafepointRegistersScope scope(this);
- __ push(object);
- __ xor_(esi, esi);
- __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance);
- RecordSafepointWithRegisters(
- instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
-
- __ test(eax, Immediate(kSmiTagMask));
- }
- DeoptimizeIf(zero, instr->environment());
+void LCodeGen::DoCheckMapCommon(Register reg,
+ Handle<Map> map,
+ LInstruction* instr) {
+ Label success;
+ __ CompareMap(reg, map, &success);
+ DeoptimizeIf(not_equal, instr->environment());
+ __ bind(&success);
}
void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
- class DeferredCheckMaps: public LDeferredCode {
- public:
- DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
- : LDeferredCode(codegen), instr_(instr), object_(object) {
- SetExit(check_maps());
- }
- virtual void Generate() {
- codegen()->DoDeferredInstanceMigration(instr_, object_);
- }
- Label* check_maps() { return &check_maps_; }
- virtual LInstruction* instr() { return instr_; }
- private:
- LCheckMaps* instr_;
- Label check_maps_;
- Register object_;
- };
-
if (instr->hydrogen()->CanOmitMapChecks()) return;
-
LOperand* input = instr->value();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
- SmallMapList* map_set = instr->hydrogen()->map_set();
-
- DeferredCheckMaps* deferred = NULL;
- if (instr->hydrogen()->has_migration_target()) {
- deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
- __ bind(deferred->check_maps());
- }
-
Label success;
+ SmallMapList* map_set = instr->hydrogen()->map_set();
for (int i = 0; i < map_set->length() - 1; i++) {
Handle<Map> map = map_set->at(i);
__ CompareMap(reg, map, &success);
__ j(equal, &success);
}
-
Handle<Map> map = map_set->last();
- __ CompareMap(reg, map, &success);
- if (instr->hydrogen()->has_migration_target()) {
- __ j(not_equal, deferred->entry());
- } else {
- DeoptimizeIf(not_equal, instr->environment());
- }
-
+ DoCheckMapCommon(reg, map, instr);
__ bind(&success);
}
@@ -5950,6 +5994,22 @@ void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
}
+void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
+ if (instr->hydrogen()->CanOmitPrototypeChecks()) return;
+ Register reg = ToRegister(instr->temp());
+
+ ZoneList<Handle<JSObject> >* prototypes = instr->prototypes();
+ ZoneList<Handle<Map> >* maps = instr->maps();
+
+ ASSERT(prototypes->length() == maps->length());
+
+ for (int i = 0; i < prototypes->length(); i++) {
+ __ LoadHeapObject(reg, prototypes->at(i));
+ DoCheckMapCommon(reg, maps->at(i), instr);
+ }
+}
+
+
void LCodeGen::DoAllocate(LAllocate* instr) {
class DeferredAllocate: public LDeferredCode {
public:
@@ -6277,7 +6337,6 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
if (info()->IsStub() && type == Deoptimizer::EAGER) {
type = Deoptimizer::LAZY;
}
- Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
DeoptimizeIf(no_condition, instr->environment(), type);
}
diff --git a/chromium/v8/src/ia32/lithium-codegen-ia32.h b/chromium/v8/src/ia32/lithium-codegen-ia32.h
index aa8f6c248a3..0beef85f0bc 100644
--- a/chromium/v8/src/ia32/lithium-codegen-ia32.h
+++ b/chromium/v8/src/ia32/lithium-codegen-ia32.h
@@ -71,8 +71,7 @@ class LCodeGen BASE_EMBEDDED {
x87_stack_depth_(0),
safepoints_(info->zone()),
resolver_(this),
- expected_safepoint_kind_(Safepoint::kSimple),
- old_position_(RelocInfo::kNoPosition) {
+ expected_safepoint_kind_(Safepoint::kSimple) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
}
@@ -164,7 +163,8 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
- void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
+
+ void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
// Parallel move support.
void DoParallelMove(LParallelMove* move);
@@ -212,7 +212,7 @@ class LCodeGen BASE_EMBEDDED {
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
void FPRINTF_CHECKING Comment(const char* format, ...);
void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
@@ -282,13 +282,10 @@ class LCodeGen BASE_EMBEDDED {
void DeoptimizeIf(Condition cc, LEnvironment* environment);
void ApplyCheckIf(Condition cc, LBoundsCheck* check);
- void AddToTranslation(LEnvironment* environment,
- Translation* translation,
+ void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -298,7 +295,7 @@ class LCodeGen BASE_EMBEDDED {
Register ToRegister(int index) const;
XMMRegister ToDoubleRegister(int index) const;
X87Register ToX87Register(int index) const;
- int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
+ int ToRepresentation(LConstantOperand* op, const Representation& r) const;
int32_t ToInteger32(LConstantOperand* op) const;
ExternalReference ToExternalReference(LConstantOperand* op) const;
@@ -323,14 +320,10 @@ class LCodeGen BASE_EMBEDDED {
Safepoint::DeoptMode mode);
void RecordPosition(int position);
- void RecordAndUpdatePosition(int position);
-
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
template<class InstrType>
void EmitBranch(InstrType instr, Condition cc);
- template<class InstrType>
- void EmitFalseBranch(InstrType instr, Condition cc);
void EmitNumberUntagD(
Register input,
Register temp,
@@ -377,6 +370,12 @@ class LCodeGen BASE_EMBEDDED {
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp);
+ void EmitLoadFieldOrConstant(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env);
+
// Emits optimized code to deep-copy the contents of statically known
// object graphs (e.g. object literal boilerplate).
void EmitDeepCopy(Handle<JSObject> object,
@@ -450,8 +449,6 @@ class LCodeGen BASE_EMBEDDED {
Safepoint::Kind expected_safepoint_kind_;
- int old_position_;
-
class PushSafepointRegistersScope BASE_EMBEDDED {
public:
explicit PushSafepointRegistersScope(LCodeGen* codegen)
diff --git a/chromium/v8/src/ia32/lithium-ia32.cc b/chromium/v8/src/ia32/lithium-ia32.cc
index b3158685fcf..ea07c5a1991 100644
--- a/chromium/v8/src/ia32/lithium-ia32.cc
+++ b/chromium/v8/src/ia32/lithium-ia32.cc
@@ -487,7 +487,7 @@ LPlatformChunk* LChunkBuilder::Build() {
}
-void LChunkBuilder::Abort(BailoutReason reason) {
+void LChunkBuilder::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -645,10 +645,8 @@ LInstruction* LChunkBuilder::DefineFixedDouble(
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
HEnvironment* hydrogen_env = current_block_->last_environment();
int argument_index_accumulator = 0;
- ZoneList<HValue*> objects_to_materialize(0, zone());
instr->set_environment(CreateEnvironment(hydrogen_env,
- &argument_index_accumulator,
- &objects_to_materialize));
+ &argument_index_accumulator));
return instr;
}
@@ -700,7 +698,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
- Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
+ Abort("Out of virtual registers while trying to allocate temp register.");
vreg = 0;
}
operand->set_virtual_register(vreg);
@@ -940,7 +938,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
}
#endif
- instr->set_position(position_);
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -956,13 +953,11 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LEnvironment* LChunkBuilder::CreateEnvironment(
HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize) {
+ int* argument_index_accumulator) {
if (hydrogen_env == NULL) return NULL;
- LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
- argument_index_accumulator,
- objects_to_materialize);
+ LEnvironment* outer =
+ CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
@@ -977,16 +972,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- int object_index = objects_to_materialize->length();
for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
- LOperand* op;
HValue* value = hydrogen_env->values()->at(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
+ LOperand* op = NULL;
+ if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
+ op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
} else {
@@ -997,33 +992,15 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
value->CheckFlag(HInstruction::kUint32));
}
- for (int i = object_index; i < objects_to_materialize->length(); ++i) {
- HValue* object_to_materialize = objects_to_materialize->at(i);
- int previously_materialized_object = -1;
- for (int prev = 0; prev < i; ++prev) {
- if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
- previously_materialized_object = prev;
- break;
- }
- }
- int length = object_to_materialize->OperandCount();
- bool is_arguments = object_to_materialize->IsArgumentsObject();
- if (previously_materialized_object >= 0) {
- result->AddDuplicateObject(previously_materialized_object);
- continue;
- } else {
- result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
- }
- for (int i = is_arguments ? 1 : 0; i < length; ++i) {
- LOperand* op;
- HValue* value = object_to_materialize->OperandAt(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
- } else {
- ASSERT(!value->IsPushArgument());
- op = UseAny(value);
- }
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ LOperand* op = UseAny(value);
result->AddValue(op,
value->representation(),
value->CheckFlag(HInstruction::kUint32));
@@ -1415,8 +1392,9 @@ LInstruction* LChunkBuilder::DoShl(HShl* instr) {
LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
if (instr->representation().IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(instr->representation()));
- ASSERT(instr->right()->representation().Equals(instr->representation()));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->right()->representation().Equals(
+ instr->left()->representation()));
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
@@ -1436,6 +1414,16 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
}
+LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
+ ASSERT(instr->value()->representation().IsInteger32());
+ ASSERT(instr->representation().IsInteger32());
+ if (instr->HasNoUses()) return NULL;
+ LOperand* input = UseRegisterAtStart(instr->value());
+ LBitNotI* result = new(zone()) LBitNotI(input);
+ return DefineSameAsFirst(result);
+}
+
+
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
@@ -1524,8 +1512,8 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
HValue* left = instr->left();
HValue* right = instr->right();
if (instr->representation().IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(instr->representation()));
- ASSERT(instr->right()->representation().Equals(instr->representation()));
+ ASSERT(left->representation().IsSmiOrInteger32());
+ ASSERT(right->representation().Equals(left->representation()));
if (instr->HasPowerOf2Divisor()) {
ASSERT(!right->CanBeZero());
@@ -1601,8 +1589,9 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
LInstruction* LChunkBuilder::DoSub(HSub* instr) {
if (instr->representation().IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(instr->representation()));
- ASSERT(instr->right()->representation().Equals(instr->representation()));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->right()->representation().Equals(
+ instr->left()->representation()));
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
LSubI* sub = new(zone()) LSubI(left, right);
@@ -1622,8 +1611,9 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
if (instr->representation().IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(instr->representation()));
- ASSERT(instr->right()->representation().Equals(instr->representation()));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->right()->representation().Equals(
+ instr->left()->representation()));
// Check to see if it would be advantageous to use an lea instruction rather
// than an add. This is the case when no overflow check is needed and there
// are multiple uses of the add's inputs, so using a 3-register add will
@@ -1656,8 +1646,9 @@ LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
LOperand* left = NULL;
LOperand* right = NULL;
if (instr->representation().IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(instr->representation()));
- ASSERT(instr->right()->representation().Equals(instr->representation()));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->right()->representation().Equals(
+ instr->left()->representation()));
left = UseRegisterAtStart(instr->BetterLeftOperand());
right = UseOrConstantAtStart(instr->BetterRightOperand());
} else {
@@ -1712,8 +1703,9 @@ LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(r));
- ASSERT(instr->right()->representation().Equals(r));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->left()->representation().Equals(
+ instr->right()->representation()));
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
return new(zone()) LCompareNumericAndBranch(left, right);
@@ -1743,13 +1735,6 @@ LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
}
-LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
- HCompareHoleAndBranch* instr) {
- LOperand* object = UseRegisterAtStart(instr->object());
- return new(zone()) LCmpHoleAndBranch(object);
-}
-
-
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ASSERT(instr->value()->representation().IsSmiOrTagged());
LOperand* temp = TempRegister();
@@ -1866,6 +1851,17 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
+LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
+ return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
return AssignEnvironment(new(zone()) LBoundsCheck(
UseRegisterOrConstantAtStart(instr->index()),
@@ -2053,6 +2049,15 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
}
+LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
+ LUnallocated* temp = NULL;
+ if (!instr->CanOmitPrototypeChecks()) temp = TempRegister();
+ LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp);
+ if (instr->CanOmitPrototypeChecks()) return result;
+ return AssignEnvironment(result);
+}
+
+
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
// If the target is in new space, we'll emit a global cell compare and so
// want the value in a register. If the target gets promoted before we
@@ -2066,16 +2071,10 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
LOperand* value = NULL;
- if (!instr->CanOmitMapChecks()) {
- value = UseRegisterAtStart(instr->value());
- if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
- }
+ if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
LCheckMaps* result = new(zone()) LCheckMaps(value);
- if (!instr->CanOmitMapChecks()) {
- AssignEnvironment(result);
- if (instr->has_migration_target()) return AssignPointerMap(result);
- }
- return result;
+ if (instr->CanOmitMapChecks()) return result;
+ return AssignEnvironment(result);
}
@@ -2207,6 +2206,25 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
}
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+ HLoadNamedFieldPolymorphic* instr) {
+ ASSERT(instr->representation().IsTagged());
+ if (instr->need_generic()) {
+ LOperand* context = UseFixed(instr->context(), esi);
+ LOperand* obj = UseFixed(instr->object(), edx);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(context, obj);
+ return MarkAsCall(DefineFixed(result, eax), instr);
+ } else {
+ LOperand* context = UseAny(instr->context()); // Not actually used.
+ LOperand* obj = UseRegisterAtStart(instr->object());
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(context, obj);
+ return AssignEnvironment(DefineAsRegister(result));
+ }
+}
+
+
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* object = UseFixed(instr->object(), edx);
@@ -2400,7 +2418,7 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool is_external_location = instr->access().IsExternalMemory() &&
instr->access().offset() == 0;
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
+ bool needs_write_barrier_for_map = !instr->transition().is_null() &&
instr->NeedsWriteBarrierForMap();
LOperand* obj;
@@ -2549,7 +2567,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
- Abort(kTooManySpillSlotsNeededForOSR);
+ Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
@@ -2573,12 +2591,6 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
}
-LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
- // There are no real uses of a captured object.
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
info()->MarkAsRequiresFrame();
LOperand* args = UseRegister(instr->arguments());
diff --git a/chromium/v8/src/ia32/lithium-ia32.h b/chromium/v8/src/ia32/lithium-ia32.h
index 7ae87a08c8d..6b0f9d0a74c 100644
--- a/chromium/v8/src/ia32/lithium-ia32.h
+++ b/chromium/v8/src/ia32/lithium-ia32.h
@@ -50,6 +50,7 @@ class LCodeGen;
V(ArithmeticD) \
V(ArithmeticT) \
V(BitI) \
+ V(BitNotI) \
V(BoundsCheck) \
V(Branch) \
V(CallConstantFunction) \
@@ -67,6 +68,7 @@ class LCodeGen;
V(CheckMaps) \
V(CheckMapValue) \
V(CheckNonSmi) \
+ V(CheckPrototypeMaps) \
V(CheckSmi) \
V(ClampDToUint8) \
V(ClampIToUint8) \
@@ -75,7 +77,6 @@ class LCodeGen;
V(ClassOfTestAndBranch) \
V(CompareNumericAndBranch) \
V(CmpObjectEqAndBranch) \
- V(CmpHoleAndBranch) \
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
@@ -128,6 +129,7 @@ class LCodeGen;
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
+ V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -209,10 +211,7 @@ class LInstruction: public ZoneObject {
LInstruction()
: environment_(NULL),
hydrogen_value_(NULL),
- bit_field_(IsCallBits::encode(false)) {
- set_position(RelocInfo::kNoPosition);
- }
-
+ is_call_(false) { }
virtual ~LInstruction() { }
virtual void CompileToNative(LCodeGen* generator) = 0;
@@ -251,28 +250,19 @@ class LInstruction: public ZoneObject {
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
- // The 31 bits PositionBits is used to store the int position value. And the
- // position value may be RelocInfo::kNoPosition (-1). The accessor always
- // +1/-1 so that the encoded value of position in bit_field_ is always >= 0
- // and can fit into the 31 bits PositionBits.
- void set_position(int pos) {
- bit_field_ = PositionBits::update(bit_field_, pos + 1);
- }
- int position() { return PositionBits::decode(bit_field_) - 1; }
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
- void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
- bool IsCall() const { return IsCallBits::decode(bit_field_); }
+ void MarkAsCall() { is_call_ = true; }
// Interface to the register allocator and iterators.
- bool ClobbersTemps() const { return IsCall(); }
- bool ClobbersRegisters() const { return IsCall(); }
+ bool ClobbersTemps() const { return is_call_; }
+ bool ClobbersRegisters() const { return is_call_; }
virtual bool ClobbersDoubleRegisters() const {
- return IsCall() ||
+ return is_call_ ||
(!CpuFeatures::IsSupported(SSE2) &&
// We only have rudimentary X87Stack tracking, thus in general
// cannot handle deoptimization nor phi-nodes.
@@ -305,13 +295,10 @@ class LInstruction: public ZoneObject {
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
- class IsCallBits: public BitField<bool, 0, 1> {};
- class PositionBits: public BitField<int, 1, 31> {};
-
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
- int bit_field_;
+ bool is_call_;
};
@@ -864,20 +851,8 @@ class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
LOperand* left() { return inputs_[0]; }
LOperand* right() { return inputs_[1]; }
- DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
-};
-
-
-class LCmpHoleAndBranch: public LControlInstruction<1, 0> {
- public:
- explicit LCmpHoleAndBranch(LOperand* object) {
- inputs_[0] = object;
- }
-
- LOperand* object() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
+ DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch,
+ "cmp-object-eq-and-branch")
};
@@ -1383,6 +1358,18 @@ class LThrow: public LTemplateInstruction<0, 2, 0> {
};
+class LBitNotI: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LBitNotI(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ LOperand* value() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
+};
+
+
class LAddI: public LTemplateInstruction<1, 2, 0> {
public:
LAddI(LOperand* left, LOperand* right) {
@@ -1536,6 +1523,21 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
};
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadNamedFieldPolymorphic(LOperand* context, LOperand* object) {
+ inputs_[0] = context;
+ inputs_[1] = object;
+ }
+
+ LOperand* context() { return inputs_[0]; }
+ LOperand* object() { return inputs_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+ DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+};
+
+
class LLoadNamedGeneric: public LTemplateInstruction<1, 2, 0> {
public:
LLoadNamedGeneric(LOperand* context, LOperand* object) {
@@ -2234,7 +2236,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 2> {
virtual void PrintDataTo(StringStream* stream);
- Handle<Map> transition() const { return hydrogen()->transition_map(); }
+ Handle<Map> transition() const { return hydrogen()->transition(); }
Representation representation() const {
return hydrogen()->field_representation();
}
@@ -2449,6 +2451,24 @@ class LCheckMaps: public LTemplateInstruction<0, 1, 0> {
};
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 1> {
+ public:
+ explicit LCheckPrototypeMaps(LOperand* temp) {
+ temps_[0] = temp;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
+ DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
+
+ ZoneList<Handle<JSObject> >* prototypes() const {
+ return hydrogen()->prototypes();
+ }
+ ZoneList<Handle<Map> >* maps() const { return hydrogen()->maps(); }
+};
+
+
class LCheckSmi: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCheckSmi(LOperand* value) {
@@ -2780,7 +2800,7 @@ class LChunkBuilder BASE_EMBEDDED {
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
// Methods for getting operands for Use / Define / Temp.
LUnallocated* ToUnallocated(Register reg);
@@ -2869,8 +2889,7 @@ class LChunkBuilder BASE_EMBEDDED {
CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize);
+ int* argument_index_accumulator);
void VisitInstruction(HInstruction* current);
diff --git a/chromium/v8/src/ia32/macro-assembler-ia32.cc b/chromium/v8/src/ia32/macro-assembler-ia32.cc
index 67a7c0d2b49..2ab5a259321 100644
--- a/chromium/v8/src/ia32/macro-assembler-ia32.cc
+++ b/chromium/v8/src/ia32/macro-assembler-ia32.cc
@@ -54,60 +54,6 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
}
-void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
- if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
- Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
- mov(destination, value);
- return;
- }
- ExternalReference roots_array_start =
- ExternalReference::roots_array_start(isolate());
- mov(destination, Immediate(index));
- mov(destination, Operand::StaticArray(destination,
- times_pointer_size,
- roots_array_start));
-}
-
-
-void MacroAssembler::StoreRoot(Register source,
- Register scratch,
- Heap::RootListIndex index) {
- ASSERT(Heap::RootCanBeWrittenAfterInitialization(index));
- ExternalReference roots_array_start =
- ExternalReference::roots_array_start(isolate());
- mov(scratch, Immediate(index));
- mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
- source);
-}
-
-
-void MacroAssembler::CompareRoot(Register with,
- Register scratch,
- Heap::RootListIndex index) {
- ExternalReference roots_array_start =
- ExternalReference::roots_array_start(isolate());
- mov(scratch, Immediate(index));
- cmp(with, Operand::StaticArray(scratch,
- times_pointer_size,
- roots_array_start));
-}
-
-
-void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
- ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index));
- Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
- cmp(with, value);
-}
-
-
-void MacroAssembler::CompareRoot(const Operand& with,
- Heap::RootListIndex index) {
- ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index));
- Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
- cmp(with, value);
-}
-
-
void MacroAssembler::InNewSpace(
Register object,
Register scratch,
@@ -486,6 +432,21 @@ void MacroAssembler::SafePush(const Immediate& x) {
}
+void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
+ // see ROOT_ACCESSOR macro in factory.h
+ Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
+ cmp(with, value);
+}
+
+
+void MacroAssembler::CompareRoot(const Operand& with,
+ Heap::RootListIndex index) {
+ // see ROOT_ACCESSOR macro in factory.h
+ Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
+ cmp(with, value);
+}
+
+
void MacroAssembler::CmpObjectType(Register heap_object,
InstanceType type,
Register map) {
@@ -717,7 +678,7 @@ void MacroAssembler::AssertNumber(Register object) {
JumpIfSmi(object, &ok);
cmp(FieldOperand(object, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
- Check(equal, kOperandNotANumber);
+ Check(equal, "Operand not a number");
bind(&ok);
}
}
@@ -726,7 +687,7 @@ void MacroAssembler::AssertNumber(Register object) {
void MacroAssembler::AssertSmi(Register object) {
if (emit_debug_code()) {
test(object, Immediate(kSmiTagMask));
- Check(equal, kOperandIsNotASmi);
+ Check(equal, "Operand is not a smi");
}
}
@@ -734,12 +695,12 @@ void MacroAssembler::AssertSmi(Register object) {
void MacroAssembler::AssertString(Register object) {
if (emit_debug_code()) {
test(object, Immediate(kSmiTagMask));
- Check(not_equal, kOperandIsASmiAndNotAString);
+ Check(not_equal, "Operand is a smi and not a string");
push(object);
mov(object, FieldOperand(object, HeapObject::kMapOffset));
CmpInstanceType(object, FIRST_NONSTRING_TYPE);
pop(object);
- Check(below, kOperandIsNotAString);
+ Check(below, "Operand is not a string");
}
}
@@ -747,12 +708,12 @@ void MacroAssembler::AssertString(Register object) {
void MacroAssembler::AssertName(Register object) {
if (emit_debug_code()) {
test(object, Immediate(kSmiTagMask));
- Check(not_equal, kOperandIsASmiAndNotAName);
+ Check(not_equal, "Operand is a smi and not a name");
push(object);
mov(object, FieldOperand(object, HeapObject::kMapOffset));
CmpInstanceType(object, LAST_NAME_TYPE);
pop(object);
- Check(below_equal, kOperandIsNotAName);
+ Check(below_equal, "Operand is not a name");
}
}
@@ -760,7 +721,7 @@ void MacroAssembler::AssertName(Register object) {
void MacroAssembler::AssertNotSmi(Register object) {
if (emit_debug_code()) {
test(object, Immediate(kSmiTagMask));
- Check(not_equal, kOperandIsASmi);
+ Check(not_equal, "Operand is a smi");
}
}
@@ -773,7 +734,7 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(Immediate(CodeObject()));
if (emit_debug_code()) {
cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
- Check(not_equal, kCodeObjectNotProperlyPatched);
+ Check(not_equal, "code object not properly patched");
}
}
@@ -782,7 +743,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
if (emit_debug_code()) {
cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
Immediate(Smi::FromInt(type)));
- Check(equal, kStackFrameTypesMustMatch);
+ Check(equal, "stack frame types must match");
}
leave();
}
@@ -1063,7 +1024,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// When generating debug code, make sure the lexical context is set.
if (emit_debug_code()) {
cmp(scratch1, Immediate(0));
- Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
+ Check(not_equal, "we should not have an empty lexical context");
}
// Load the native context of the current context.
int offset =
@@ -1076,7 +1037,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// Read the first word and compare to native_context_map.
cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
isolate()->factory()->native_context_map());
- Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
+ Check(equal, "JSGlobalObject::native_context should be a native context.");
}
// Check if both contexts are the same.
@@ -1095,12 +1056,12 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// Check the context is a native context.
if (emit_debug_code()) {
cmp(scratch2, isolate()->factory()->null_value());
- Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
+ Check(not_equal, "JSGlobalProxy::context() should not be null.");
// Read the first word and compare to native_context_map(),
cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
isolate()->factory()->native_context_map());
- Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
+ Check(equal, "JSGlobalObject::native_context should be a native context.");
}
int token_offset = Context::kHeaderSize +
@@ -1245,7 +1206,7 @@ void MacroAssembler::LoadAllocationTopHelper(Register result,
#ifdef DEBUG
// Assert that result actually contains top on entry.
cmp(result, Operand::StaticVariable(allocation_top));
- Check(equal, kUnexpectedAllocationTop);
+ Check(equal, "Unexpected allocation top");
#endif
return;
}
@@ -1265,7 +1226,7 @@ void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
AllocationFlags flags) {
if (emit_debug_code()) {
test(result_end, Immediate(kObjectAlignmentMask));
- Check(zero, kUnalignedAllocationInNewSpace);
+ Check(zero, "Unaligned allocation in new space");
}
ExternalReference allocation_top =
@@ -1497,7 +1458,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object) {
and_(object, Immediate(~kHeapObjectTagMask));
#ifdef DEBUG
cmp(object, Operand::StaticVariable(new_space_allocation_top));
- Check(below, kUndoAllocationOfNonAllocatedMemory);
+ Check(below, "Undo allocation of non allocated memory");
#endif
mov(Operand::StaticVariable(new_space_allocation_top), object);
}
@@ -2101,7 +2062,7 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
// previous handle scope.
mov(Operand::StaticVariable(next_address), ebx);
sub(Operand::StaticVariable(level_address), Immediate(1));
- Assert(above_equal, kInvalidHandleScopeLevel);
+ Assert(above_equal, "Invalid HandleScope level");
cmp(edi, Operand::StaticVariable(limit_address));
j(not_equal, &delete_allocated_handles);
bind(&leave_exit_frame);
@@ -2143,7 +2104,7 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
cmp(return_value, isolate()->factory()->null_value());
j(equal, &ok, Label::kNear);
- Abort(kAPICallReturnedInvalidObject);
+ Abort("API call returned invalid object");
bind(&ok);
#endif
@@ -2429,7 +2390,7 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
if (emit_debug_code()) {
cmp(FieldOperand(dst, HeapObject::kMapOffset),
isolate()->factory()->with_context_map());
- Check(not_equal, kVariableResolvedToWithContext);
+ Check(not_equal, "Variable resolved to with context.");
}
}
@@ -2516,7 +2477,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
jmp(&ok);
bind(&fail);
- Abort(kGlobalFunctionsMustHaveInitialMap);
+ Abort("Global functions must have initial map");
bind(&ok);
}
}
@@ -2617,7 +2578,7 @@ void MacroAssembler::VerifyX87StackDepth(uint32_t depth) {
and_(eax, kTopMask);
shr(eax, 11);
cmp(eax, Immediate(tos));
- Check(equal, kUnexpectedFPUStackDepthAfterInstruction);
+ Check(equal, "Unexpected FPU stack depth after instruction");
fnclex();
pop(eax);
}
@@ -2700,8 +2661,8 @@ void MacroAssembler::DecrementCounter(Condition cc,
}
-void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
- if (emit_debug_code()) Check(cc, reason);
+void MacroAssembler::Assert(Condition cc, const char* msg) {
+ if (emit_debug_code()) Check(cc, msg);
}
@@ -2718,16 +2679,16 @@ void MacroAssembler::AssertFastElements(Register elements) {
cmp(FieldOperand(elements, HeapObject::kMapOffset),
Immediate(factory->fixed_cow_array_map()));
j(equal, &ok);
- Abort(kJSObjectWithFastElementsMapHasSlowElements);
+ Abort("JSObject with fast elements map has slow elements");
bind(&ok);
}
}
-void MacroAssembler::Check(Condition cc, BailoutReason reason) {
+void MacroAssembler::Check(Condition cc, const char* msg) {
Label L;
j(cc, &L);
- Abort(reason);
+ Abort(msg);
// will not return here
bind(&L);
}
@@ -2748,13 +2709,12 @@ void MacroAssembler::CheckStackAlignment() {
}
-void MacroAssembler::Abort(BailoutReason reason) {
+void MacroAssembler::Abort(const char* msg) {
// We want to pass the msg string like a smi to avoid GC
// problems, however msg is not guaranteed to be aligned
// properly. Instead, we pass an aligned pointer that is
// a proper v8 smi, but also pass the alignment difference
// from the real pointer as a smi.
- const char* msg = GetBailoutReason(reason);
intptr_t p1 = reinterpret_cast<intptr_t>(msg);
intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
@@ -3158,7 +3118,7 @@ void MacroAssembler::EnsureNotWhite(
if (emit_debug_code()) {
mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
- Check(less_equal, kLiveBytesCountOverflowChunkSize);
+ Check(less_equal, "Live Bytes Count overflow chunk size");
}
bind(&done);
diff --git a/chromium/v8/src/ia32/macro-assembler-ia32.h b/chromium/v8/src/ia32/macro-assembler-ia32.h
index d537b0b2cbd..3bca930d667 100644
--- a/chromium/v8/src/ia32/macro-assembler-ia32.h
+++ b/chromium/v8/src/ia32/macro-assembler-ia32.h
@@ -61,15 +61,6 @@ class MacroAssembler: public Assembler {
// macro assembler.
MacroAssembler(Isolate* isolate, void* buffer, int size);
- // Operations on roots in the root-array.
- void LoadRoot(Register destination, Heap::RootListIndex index);
- void StoreRoot(Register source, Register scratch, Heap::RootListIndex index);
- void CompareRoot(Register with, Register scratch, Heap::RootListIndex index);
- // These methods can only be used with constant roots (i.e. non-writable
- // and not in new space).
- void CompareRoot(Register with, Heap::RootListIndex index);
- void CompareRoot(const Operand& with, Heap::RootListIndex index);
-
// ---------------------------------------------------------------------------
// GC Support
enum RememberedSetFinalAction {
@@ -371,6 +362,10 @@ class MacroAssembler: public Assembler {
void SafeSet(Register dst, const Immediate& x);
void SafePush(const Immediate& x);
+ // Compare against a known root, e.g. undefined, null, true, ...
+ void CompareRoot(Register with, Heap::RootListIndex index);
+ void CompareRoot(const Operand& with, Heap::RootListIndex index);
+
// Compare object type for heap object.
// Incoming register is heap_object and outgoing register is map.
void CmpObjectType(Register heap_object, InstanceType type, Register map);
@@ -812,8 +807,6 @@ class MacroAssembler: public Assembler {
void Drop(int element_count);
void Call(Label* target) { call(target); }
- void Push(Register src) { push(src); }
- void Pop(Register dst) { pop(dst); }
// Emit call to the code we are currently generating.
void CallSelf() {
@@ -851,15 +844,15 @@ class MacroAssembler: public Assembler {
// Calls Abort(msg) if the condition cc is not satisfied.
// Use --debug_code to enable.
- void Assert(Condition cc, BailoutReason reason);
+ void Assert(Condition cc, const char* msg);
void AssertFastElements(Register elements);
// Like Assert(), but always enabled.
- void Check(Condition cc, BailoutReason reason);
+ void Check(Condition cc, const char* msg);
// Print a message to stdout and abort execution.
- void Abort(BailoutReason reason);
+ void Abort(const char* msg);
// Check that the stack is aligned.
void CheckStackAlignment();
diff --git a/chromium/v8/src/ia32/stub-cache-ia32.cc b/chromium/v8/src/ia32/stub-cache-ia32.cc
index df7ad4467f9..123506fa623 100644
--- a/chromium/v8/src/ia32/stub-cache-ia32.cc
+++ b/chromium/v8/src/ia32/stub-cache-ia32.cc
@@ -2479,8 +2479,6 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfNotSmi(eax, &not_smi);
- // Branchless abs implementation, refer to below:
- // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
// Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
// otherwise.
__ mov(ebx, eax);
@@ -3155,7 +3153,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ j(equal, &miss);
} else if (FLAG_debug_code) {
__ cmp(eax, factory()->the_hole_value());
- __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
+ __ Check(not_equal, "DontDelete cells can't contain the hole");
}
HandlerFrontendFooter(name, &success, &miss);
diff --git a/chromium/v8/src/ic.cc b/chromium/v8/src/ic.cc
index 3c22580c2c7..a55160a394e 100644
--- a/chromium/v8/src/ic.cc
+++ b/chromium/v8/src/ic.cc
@@ -390,6 +390,7 @@ void IC::Clear(Address address) {
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
case Code::COMPARE_IC: return CompareIC::Clear(address, target);
case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
+ case Code::UNARY_OP_IC:
case Code::BINARY_OP_IC:
case Code::TO_BOOLEAN_IC:
// Clearing these is tricky and does not
@@ -2588,6 +2589,27 @@ void BinaryOpIC::StubInfoToType(int minor_key,
}
+MaybeObject* UnaryOpIC::Transition(Handle<Object> object) {
+ Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
+ UnaryOpStub stub(extra_ic_state);
+
+ stub.UpdateStatus(object);
+
+ Handle<Code> code = stub.GetCode(isolate());
+ set_target(*code);
+
+ return stub.Result(object, isolate());
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss) {
+ HandleScope scope(isolate);
+ Handle<Object> object = args.at<Object>(0);
+ UnaryOpIC ic(isolate);
+ return ic.Transition(object);
+}
+
+
static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
Token::Value op) {
v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
diff --git a/chromium/v8/src/ic.h b/chromium/v8/src/ic.h
index fcf0de58f1a..7820d407ec1 100644
--- a/chromium/v8/src/ic.h
+++ b/chromium/v8/src/ic.h
@@ -714,6 +714,14 @@ class KeyedStoreIC: public StoreIC {
};
+class UnaryOpIC: public IC {
+ public:
+ explicit UnaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
+
+ MUST_USE_RESULT MaybeObject* Transition(Handle<Object> object);
+};
+
+
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
class BinaryOpIC: public IC {
public:
diff --git a/chromium/v8/src/isolate.cc b/chromium/v8/src/isolate.cc
index 7b77d893f15..61f1e2dcfa5 100644
--- a/chromium/v8/src/isolate.cc
+++ b/chromium/v8/src/isolate.cc
@@ -1774,7 +1774,6 @@ Isolate::Isolate()
inner_pointer_to_code_cache_(NULL),
write_iterator_(NULL),
global_handles_(NULL),
- eternal_handles_(NULL),
context_switcher_(NULL),
thread_manager_(NULL),
fp_stubs_generated_(false),
@@ -1783,6 +1782,7 @@ Isolate::Isolate()
regexp_stack_(NULL),
date_cache_(NULL),
code_stub_interface_descriptors_(NULL),
+ context_exit_happened_(false),
initialized_from_snapshot_(false),
cpu_profiler_(NULL),
heap_profiler_(NULL),
@@ -2052,8 +2052,6 @@ Isolate::~Isolate() {
code_range_ = NULL;
delete global_handles_;
global_handles_ = NULL;
- delete eternal_handles_;
- eternal_handles_ = NULL;
delete string_stream_debug_object_cache_;
string_stream_debug_object_cache_ = NULL;
@@ -2185,7 +2183,6 @@ bool Isolate::Init(Deserializer* des) {
inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
write_iterator_ = new ConsStringIteratorOp();
global_handles_ = new GlobalHandles(this);
- eternal_handles_ = new EternalHandles();
bootstrapper_ = new Bootstrapper(this);
handle_scope_implementer_ = new HandleScopeImplementer(this);
stub_cache_ = new StubCache(this);
diff --git a/chromium/v8/src/isolate.h b/chromium/v8/src/isolate.h
index 401505afdda..c0083177373 100644
--- a/chromium/v8/src/isolate.h
+++ b/chromium/v8/src/isolate.h
@@ -661,9 +661,9 @@ class Isolate {
}
inline Address* handler_address() { return &thread_local_top_.handler_; }
- // Bottom JS entry.
- Address js_entry_sp() {
- return thread_local_top_.js_entry_sp_;
+ // Bottom JS entry (see StackTracer::Trace in sampler.cc).
+ static Address js_entry_sp(ThreadLocalTop* thread) {
+ return thread->js_entry_sp_;
}
inline Address* js_entry_sp_address() {
return &thread_local_top_.js_entry_sp_;
@@ -922,8 +922,6 @@ class Isolate {
GlobalHandles* global_handles() { return global_handles_; }
- EternalHandles* eternal_handles() { return eternal_handles_; }
-
ThreadManager* thread_manager() { return thread_manager_; }
ContextSwitcher* context_switcher() { return context_switcher_; }
@@ -1062,6 +1060,13 @@ class Isolate {
thread_local_top_.top_lookup_result_ = top;
}
+ bool context_exit_happened() {
+ return context_exit_happened_;
+ }
+ void set_context_exit_happened(bool context_exit_happened) {
+ context_exit_happened_ = context_exit_happened;
+ }
+
bool initialized_from_snapshot() { return initialized_from_snapshot_; }
double time_millis_since_init() {
@@ -1290,7 +1295,6 @@ class Isolate {
InnerPointerToCodeCache* inner_pointer_to_code_cache_;
ConsStringIteratorOp* write_iterator_;
GlobalHandles* global_handles_;
- EternalHandles* eternal_handles_;
ContextSwitcher* context_switcher_;
ThreadManager* thread_manager_;
RuntimeState runtime_state_;
@@ -1310,6 +1314,10 @@ class Isolate {
unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
CodeStubInterfaceDescriptor* code_stub_interface_descriptors_;
+ // The garbage collector should be a little more aggressive when it knows
+ // that a context was recently exited.
+ bool context_exit_happened_;
+
// True if this isolate was initialized from a snapshot.
bool initialized_from_snapshot_;
diff --git a/chromium/v8/src/lithium.cc b/chromium/v8/src/lithium.cc
index 790a2182b17..e9c3531e385 100644
--- a/chromium/v8/src/lithium.cc
+++ b/chromium/v8/src/lithium.cc
@@ -425,7 +425,7 @@ LChunk* LChunk::NewChunk(HGraph* graph) {
int values = graph->GetMaximumValueID();
CompilationInfo* info = graph->info();
if (values > LUnallocated::kMaxVirtualRegisters) {
- info->set_bailout_reason(kNotEnoughVirtualRegistersForValues);
+ info->set_bailout_reason("not enough virtual registers for values");
return NULL;
}
LAllocator allocator(values, graph);
@@ -434,7 +434,7 @@ LChunk* LChunk::NewChunk(HGraph* graph) {
if (chunk == NULL) return NULL;
if (!allocator.Allocate(chunk)) {
- info->set_bailout_reason(kNotEnoughVirtualRegistersRegalloc);
+ info->set_bailout_reason("not enough virtual registers (regalloc)");
return NULL;
}
diff --git a/chromium/v8/src/lithium.h b/chromium/v8/src/lithium.h
index f773916485d..1e0784eb98d 100644
--- a/chromium/v8/src/lithium.h
+++ b/chromium/v8/src/lithium.h
@@ -533,7 +533,6 @@ class LEnvironment: public ZoneObject {
values_(value_count, zone),
is_tagged_(value_count, zone),
is_uint32_(value_count, zone),
- object_mapping_(0, zone),
outer_(outer),
entry_(entry),
zone_(zone) { }
@@ -574,38 +573,6 @@ class LEnvironment: public ZoneObject {
return is_uint32_.Contains(index);
}
- void AddNewObject(int length, bool is_arguments) {
- uint32_t encoded = LengthOrDupeField::encode(length) |
- IsArgumentsField::encode(is_arguments) |
- IsDuplicateField::encode(false);
- object_mapping_.Add(encoded, zone());
- }
-
- void AddDuplicateObject(int dupe_of) {
- uint32_t encoded = LengthOrDupeField::encode(dupe_of) |
- IsDuplicateField::encode(true);
- object_mapping_.Add(encoded, zone());
- }
-
- int ObjectDuplicateOfAt(int index) {
- ASSERT(ObjectIsDuplicateAt(index));
- return LengthOrDupeField::decode(object_mapping_[index]);
- }
-
- int ObjectLengthAt(int index) {
- ASSERT(!ObjectIsDuplicateAt(index));
- return LengthOrDupeField::decode(object_mapping_[index]);
- }
-
- bool ObjectIsArgumentsAt(int index) {
- ASSERT(!ObjectIsDuplicateAt(index));
- return IsArgumentsField::decode(object_mapping_[index]);
- }
-
- bool ObjectIsDuplicateAt(int index) {
- return IsDuplicateField::decode(object_mapping_[index]);
- }
-
void Register(int deoptimization_index,
int translation_index,
int pc_offset) {
@@ -620,14 +587,6 @@ class LEnvironment: public ZoneObject {
void PrintTo(StringStream* stream);
- // Marker value indicating a de-materialized object.
- static LOperand* materialization_marker() { return NULL; }
-
- // Encoding used for the object_mapping map below.
- class LengthOrDupeField : public BitField<int, 0, 30> { };
- class IsArgumentsField : public BitField<bool, 30, 1> { };
- class IsDuplicateField : public BitField<bool, 31, 1> { };
-
private:
Handle<JSFunction> closure_;
FrameType frame_type_;
@@ -644,10 +603,6 @@ class LEnvironment: public ZoneObject {
ZoneList<LOperand*> values_;
GrowableBitVector is_tagged_;
GrowableBitVector is_uint32_;
-
- // Map with encoded information about materialization_marker operands.
- ZoneList<uint32_t> object_mapping_;
-
LEnvironment* outer_;
HEnterInlined* entry_;
Zone* zone_;
@@ -799,7 +754,8 @@ int StackSlotOffset(int index);
enum NumberUntagDMode {
NUMBER_CANDIDATE_IS_SMI,
- NUMBER_CANDIDATE_IS_ANY_TAGGED
+ NUMBER_CANDIDATE_IS_ANY_TAGGED,
+ NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE
};
diff --git a/chromium/v8/src/liveedit.cc b/chromium/v8/src/liveedit.cc
index 406510a3b86..859cf2b94f3 100644
--- a/chromium/v8/src/liveedit.cc
+++ b/chromium/v8/src/liveedit.cc
@@ -1290,7 +1290,6 @@ MaybeObject* LiveEdit::ReplaceFunctionCode(
if (code_scope_info->IsFixedArray()) {
shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
}
- shared_info->DisableOptimization(kLiveEdit);
}
if (shared_info->debug_info()->IsDebugInfo()) {
diff --git a/chromium/v8/src/log.cc b/chromium/v8/src/log.cc
index a1e5a6752b1..b89c2bfba01 100644
--- a/chromium/v8/src/log.cc
+++ b/chromium/v8/src/log.cc
@@ -1644,6 +1644,7 @@ void Logger::LogCodeObject(Object* object) {
case Code::FUNCTION:
case Code::OPTIMIZED_FUNCTION:
return; // We log this later using LogCompiledFunctions.
+ case Code::UNARY_OP_IC: // fall through
case Code::BINARY_OP_IC: // fall through
case Code::COMPARE_IC: // fall through
case Code::COMPARE_NIL_IC: // fall through
diff --git a/chromium/v8/src/mark-compact.cc b/chromium/v8/src/mark-compact.cc
index 0e842670280..91da8a0117a 100644
--- a/chromium/v8/src/mark-compact.cc
+++ b/chromium/v8/src/mark-compact.cc
@@ -431,8 +431,8 @@ void MarkCompactCollector::CollectGarbage() {
heap()->weak_embedded_maps_verification_enabled()) {
VerifyWeakEmbeddedMapsInOptimizedCode();
}
- if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) {
- VerifyOmittedMapChecks();
+ if (FLAG_collect_maps && FLAG_omit_prototype_checks_for_leaf_maps) {
+ VerifyOmittedPrototypeChecks();
}
#endif
@@ -503,13 +503,13 @@ void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() {
}
-void MarkCompactCollector::VerifyOmittedMapChecks() {
+void MarkCompactCollector::VerifyOmittedPrototypeChecks() {
HeapObjectIterator iterator(heap()->map_space());
for (HeapObject* obj = iterator.Next();
obj != NULL;
obj = iterator.Next()) {
Map* map = Map::cast(obj);
- map->VerifyOmittedMapChecks();
+ map->VerifyOmittedPrototypeChecks();
}
}
#endif // VERIFY_HEAP
diff --git a/chromium/v8/src/mark-compact.h b/chromium/v8/src/mark-compact.h
index ee845a08370..16e49e10295 100644
--- a/chromium/v8/src/mark-compact.h
+++ b/chromium/v8/src/mark-compact.h
@@ -638,7 +638,7 @@ class MarkCompactCollector {
static void VerifyMarkbitsAreClean(PagedSpace* space);
static void VerifyMarkbitsAreClean(NewSpace* space);
void VerifyWeakEmbeddedMapsInOptimizedCode();
- void VerifyOmittedMapChecks();
+ void VerifyOmittedPrototypeChecks();
#endif
// Sweep a single page from the given space conservatively.
diff --git a/chromium/v8/src/messages.js b/chromium/v8/src/messages.js
index 2debbf86540..b586d24882b 100644
--- a/chromium/v8/src/messages.js
+++ b/chromium/v8/src/messages.js
@@ -228,18 +228,16 @@ function NoSideEffectToString(obj) {
}
}
}
- if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
- return %_CallFunction(obj, ErrorToString);
- }
+ if (IsNativeErrorObject(obj)) return %_CallFunction(obj, ErrorToString);
return %_CallFunction(obj, ObjectToString);
}
-// To determine whether we can safely stringify an object using ErrorToString
-// without the risk of side-effects, we need to check whether the object is
-// either an instance of a native error type (via '%_ClassOf'), or has $Error
-// in its prototype chain and hasn't overwritten 'toString' with something
-// strange and unusual.
-function CanBeSafelyTreatedAsAnErrorObject(obj) {
+
+// To check if something is a native error we need to check the
+// concrete native error types. It is not sufficient to use instanceof
+// since it possible to create an object that has Error.prototype on
+// its prototype chain. This is the case for DOMException for example.
+function IsNativeErrorObject(obj) {
switch (%_ClassOf(obj)) {
case 'Error':
case 'EvalError':
@@ -250,9 +248,7 @@ function CanBeSafelyTreatedAsAnErrorObject(obj) {
case 'URIError':
return true;
}
-
- var objToString = %GetDataProperty(obj, "toString");
- return obj instanceof $Error && objToString === ErrorToString;
+ return false;
}
@@ -261,7 +257,7 @@ function CanBeSafelyTreatedAsAnErrorObject(obj) {
// the error to string method. This is to avoid leaking error
// objects between script tags in a browser setting.
function ToStringCheckErrorObject(obj) {
- if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
+ if (IsNativeErrorObject(obj)) {
return %_CallFunction(obj, ErrorToString);
} else {
return ToString(obj);
diff --git a/chromium/v8/src/mips/assembler-mips.h b/chromium/v8/src/mips/assembler-mips.h
index cb0896a8ded..8d533b36f40 100644
--- a/chromium/v8/src/mips/assembler-mips.h
+++ b/chromium/v8/src/mips/assembler-mips.h
@@ -358,11 +358,6 @@ class Operand BASE_EMBEDDED {
// Return true if this is a register operand.
INLINE(bool is_reg() const);
- inline int32_t immediate() const {
- ASSERT(!is_reg());
- return imm32_;
- }
-
Register rm() const { return rm_; }
private:
diff --git a/chromium/v8/src/mips/builtins-mips.cc b/chromium/v8/src/mips/builtins-mips.cc
index d424cbc7261..3f5dca00096 100644
--- a/chromium/v8/src/mips/builtins-mips.cc
+++ b/chromium/v8/src/mips/builtins-mips.cc
@@ -123,10 +123,10 @@ void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
// Initial map for the builtin InternalArray functions should be maps.
__ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
__ And(t0, a2, Operand(kSmiTagMask));
- __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
+ __ Assert(ne, "Unexpected initial map for InternalArray function",
t0, Operand(zero_reg));
__ GetObjectType(a2, a3, t0);
- __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
+ __ Assert(eq, "Unexpected initial map for InternalArray function",
t0, Operand(MAP_TYPE));
}
@@ -153,10 +153,10 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
// Initial map for the builtin Array functions should be maps.
__ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
__ And(t0, a2, Operand(kSmiTagMask));
- __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
+ __ Assert(ne, "Unexpected initial map for Array function (1)",
t0, Operand(zero_reg));
__ GetObjectType(a2, a3, t0);
- __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
+ __ Assert(eq, "Unexpected initial map for Array function (2)",
t0, Operand(MAP_TYPE));
}
@@ -185,7 +185,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
Register function = a1;
if (FLAG_debug_code) {
__ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2);
- __ Assert(eq, kUnexpectedStringFunction, function, Operand(a2));
+ __ Assert(eq, "Unexpected String function", function, Operand(a2));
}
// Load the first arguments in a0 and get rid of the rest.
@@ -231,10 +231,10 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
__ LoadGlobalFunctionInitialMap(function, map, t0);
if (FLAG_debug_code) {
__ lbu(t0, FieldMemOperand(map, Map::kInstanceSizeOffset));
- __ Assert(eq, kUnexpectedStringWrapperInstanceSize,
+ __ Assert(eq, "Unexpected string wrapper instance size",
t0, Operand(JSValue::kSize >> kPointerSizeLog2));
__ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
- __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper,
+ __ Assert(eq, "Unexpected unused properties of string wrapper",
t0, Operand(zero_reg));
}
__ sw(map, FieldMemOperand(v0, HeapObject::kMapOffset));
@@ -489,7 +489,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ addu(a0, t5, t0);
// a0: offset of first field after pre-allocated fields
if (FLAG_debug_code) {
- __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
+ __ Assert(le, "Unexpected number of pre-allocated property fields.",
a0, Operand(t6));
}
__ InitializeFieldsWithFiller(t5, a0, t7);
@@ -522,7 +522,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Done if no extra properties are to be allocated.
__ Branch(&allocated, eq, a3, Operand(zero_reg));
- __ Assert(greater_equal, kPropertyAllocationCountFailed,
+ __ Assert(greater_equal, "Property allocation count failed.",
a3, Operand(zero_reg));
// Scale the number of elements by pointer size and add the header for
@@ -569,7 +569,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
} else if (FLAG_debug_code) {
__ LoadRoot(t8, Heap::kUndefinedValueRootIndex);
- __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t8));
+ __ Assert(eq, "Undefined value not loaded.", t7, Operand(t8));
}
__ jmp(&entry);
__ bind(&loop);
diff --git a/chromium/v8/src/mips/code-stubs-mips.cc b/chromium/v8/src/mips/code-stubs-mips.cc
index 8a03a9a31a5..0e1b224eadf 100644
--- a/chromium/v8/src/mips/code-stubs-mips.cc
+++ b/chromium/v8/src/mips/code-stubs-mips.cc
@@ -247,6 +247,17 @@ void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
}
+void UnaryOpStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { a0 };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
void StoreGlobalStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -509,7 +520,8 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
Label after_sentinel;
__ JumpIfNotSmi(a3, &after_sentinel);
if (FLAG_debug_code) {
- __ Assert(eq, kExpected0AsASmiSentinel, a3, Operand(zero_reg));
+ const char* message = "Expected 0 as a Smi sentinel";
+ __ Assert(eq, message, a3, Operand(zero_reg));
}
__ lw(a3, GlobalObjectOperand());
__ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset));
@@ -667,7 +679,7 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
Label* not_number) {
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
- kHeapNumberMapRegisterClobbered);
+ "HeapNumberMap register clobbered.");
Label is_smi, done;
@@ -717,7 +729,7 @@ void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
Label* not_number) {
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
- kHeapNumberMapRegisterClobbered);
+ "HeapNumberMap register clobbered.");
Label done;
Label not_in_int32_range;
@@ -794,7 +806,7 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
__ bind(&obj_is_not_smi);
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
- kHeapNumberMapRegisterClobbered);
+ "HeapNumberMap register clobbered.");
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
// Load the number.
@@ -841,7 +853,7 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
- kHeapNumberMapRegisterClobbered);
+ "HeapNumberMap register clobbered.");
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined);
@@ -4267,12 +4279,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ And(t0, regexp_data, Operand(kSmiTagMask));
__ Check(nz,
- kUnexpectedTypeForRegExpDataFixedArrayExpected,
+ "Unexpected type for RegExp data, FixedArray expected",
t0,
Operand(zero_reg));
__ GetObjectType(regexp_data, a0, a0);
__ Check(eq,
- kUnexpectedTypeForRegExpDataFixedArrayExpected,
+ "Unexpected type for RegExp data, FixedArray expected",
a0,
Operand(FIXED_ARRAY_TYPE));
}
@@ -4627,7 +4639,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Sequential strings have already been ruled out.
__ And(at, a0, Operand(kIsIndirectStringMask));
__ Assert(eq,
- kExternalStringExpectedButNotFound,
+ "external string expected, but not found",
at,
Operand(zero_reg));
}
@@ -5008,7 +5020,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharCodeAtGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough to CharCodeAt slow case");
// Index is not a smi.
__ bind(&index_not_smi_);
@@ -5057,7 +5069,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough from CharCodeAt slow case");
}
@@ -5094,7 +5106,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough to CharFromCode slow case");
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
@@ -5105,7 +5117,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ Branch(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough from CharFromCode slow case");
}
@@ -5160,7 +5172,7 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
// that it is.
__ And(scratch4, dest, Operand(kPointerAlignmentMask));
__ Check(eq,
- kDestinationOfCopyNotAligned,
+ "Destination of copy not aligned.",
scratch4,
Operand(zero_reg));
}
@@ -5360,7 +5372,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
// Must be the hole (deleted entry).
if (FLAG_debug_code) {
__ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
- __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole,
+ __ Assert(eq, "oddball in string table is not undefined or the hole",
scratch, Operand(candidate));
}
__ jmp(&next_probe[i]);
@@ -6568,7 +6580,7 @@ void DirectCEntryStub::Generate(MacroAssembler* masm) {
// filled with kZapValue by the GC.
// Dereference the address and check for this.
__ lw(t0, MemOperand(t9));
- __ Assert(ne, kReceivedInvalidReturnAddress, t0,
+ __ Assert(ne, "Received invalid return address.", t0,
Operand(reinterpret_cast<uint32_t>(kZapValue)));
}
__ Jump(t9);
@@ -7319,7 +7331,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -7374,7 +7386,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -7435,10 +7447,10 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ And(at, a3, Operand(kSmiTagMask));
- __ Assert(ne, kUnexpectedInitialMapForArrayFunction,
+ __ Assert(ne, "Unexpected initial map for Array function",
at, Operand(zero_reg));
__ GetObjectType(a3, a3, t0);
- __ Assert(eq, kUnexpectedInitialMapForArrayFunction,
+ __ Assert(eq, "Unexpected initial map for Array function",
t0, Operand(MAP_TYPE));
// We should either have undefined in a2 or a valid cell.
@@ -7447,7 +7459,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(&okay_here, eq, a2, Operand(at));
__ lw(a3, FieldMemOperand(a2, 0));
- __ Assert(eq, kExpectedPropertyCellInRegisterA2,
+ __ Assert(eq, "Expected property cell in register a2",
a3, Operand(cell_map));
__ bind(&okay_here);
}
@@ -7547,10 +7559,10 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ And(at, a3, Operand(kSmiTagMask));
- __ Assert(ne, kUnexpectedInitialMapForArrayFunction,
+ __ Assert(ne, "Unexpected initial map for Array function",
at, Operand(zero_reg));
__ GetObjectType(a3, a3, t0);
- __ Assert(eq, kUnexpectedInitialMapForArrayFunction,
+ __ Assert(eq, "Unexpected initial map for Array function",
t0, Operand(MAP_TYPE));
}
@@ -7567,7 +7579,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
Label done;
__ Branch(&done, eq, a3, Operand(FAST_ELEMENTS));
__ Assert(
- eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray,
+ eq, "Invalid ElementsKind for InternalArray or InternalPackedArray",
a3, Operand(FAST_HOLEY_ELEMENTS));
__ bind(&done);
}
diff --git a/chromium/v8/src/mips/codegen-mips.cc b/chromium/v8/src/mips/codegen-mips.cc
index 5c847fc8f62..3f74154f58a 100644
--- a/chromium/v8/src/mips/codegen-mips.cc
+++ b/chromium/v8/src/mips/codegen-mips.cc
@@ -205,7 +205,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
// Allocate new FixedDoubleArray.
__ sll(scratch, t1, 2);
__ Addu(scratch, scratch, FixedDoubleArray::kHeaderSize);
- __ Allocate(scratch, t2, t3, t5, &gc_required, DOUBLE_ALIGNMENT);
+ __ 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.
@@ -289,7 +289,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
__ SmiTag(t5);
__ Or(t5, t5, Operand(1));
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
- __ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(t5));
+ __ Assert(eq, "object found in smi-only array", at, Operand(t5));
}
__ sw(t0, MemOperand(t3)); // mantissa
__ sw(t1, MemOperand(t3, kIntSize)); // exponent
@@ -489,7 +489,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ And(at, result, Operand(kIsIndirectStringMask));
- __ Assert(eq, kExternalStringExpectedButNotFound,
+ __ Assert(eq, "external string expected, but not found",
at, Operand(zero_reg));
}
// Rule out short external strings.
diff --git a/chromium/v8/src/mips/debug-mips.cc b/chromium/v8/src/mips/debug-mips.cc
index 020228fc6b5..30cc4db6340 100644
--- a/chromium/v8/src/mips/debug-mips.cc
+++ b/chromium/v8/src/mips/debug-mips.cc
@@ -142,7 +142,8 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
if ((non_object_regs & (1 << r)) != 0) {
if (FLAG_debug_code) {
__ And(at, reg, 0xc0000000);
- __ Assert(eq, kUnableToEncodeValueAsSmi, at, Operand(zero_reg));
+ __ Assert(
+ eq, "Unable to encode value as smi", at, Operand(zero_reg));
}
__ sll(reg, reg, kSmiTagSize);
}
@@ -324,12 +325,12 @@ void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
- masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnMips);
+ masm->Abort("LiveEdit frame dropping is not supported on mips");
}
void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
- masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnMips);
+ masm->Abort("LiveEdit frame dropping is not supported on mips");
}
diff --git a/chromium/v8/src/mips/full-codegen-mips.cc b/chromium/v8/src/mips/full-codegen-mips.cc
index b60502c9a5b..1084af09298 100644
--- a/chromium/v8/src/mips/full-codegen-mips.cc
+++ b/chromium/v8/src/mips/full-codegen-mips.cc
@@ -786,10 +786,10 @@ void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
// Check that we're not inside a with or catch context.
__ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
__ LoadRoot(t0, Heap::kWithContextMapRootIndex);
- __ Check(ne, kDeclarationInWithContext,
+ __ Check(ne, "Declaration in with context.",
a1, Operand(t0));
__ LoadRoot(t0, Heap::kCatchContextMapRootIndex);
- __ Check(ne, kDeclarationInCatchContext,
+ __ Check(ne, "Declaration in catch context.",
a1, Operand(t0));
}
}
@@ -2529,7 +2529,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Check for an uninitialized let binding.
__ lw(a2, location);
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
- __ Check(eq, kLetBindingReInitialization, a2, Operand(t0));
+ __ Check(eq, "Let binding re-initialization.", a2, Operand(t0));
}
// Perform the assignment.
__ sw(v0, location);
@@ -3492,21 +3492,21 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
Register value,
uint32_t encoding_mask) {
__ And(at, index, Operand(kSmiTagMask));
- __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
+ __ Check(eq, "Non-smi index", at, Operand(zero_reg));
__ And(at, value, Operand(kSmiTagMask));
- __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
+ __ Check(eq, "Non-smi value", at, Operand(zero_reg));
__ lw(at, FieldMemOperand(string, String::kLengthOffset));
- __ Check(lt, kIndexIsTooLarge, index, Operand(at));
+ __ Check(lt, "Index is too large", index, Operand(at));
- __ Check(ge, kIndexIsNegative, index, Operand(zero_reg));
+ __ Check(ge, "Index is negative", index, Operand(zero_reg));
__ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
__ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
__ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
__ Subu(at, at, Operand(encoding_mask));
- __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
+ __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
}
@@ -3881,7 +3881,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
Handle<FixedArray> jsfunction_result_caches(
isolate()->native_context()->jsfunction_result_caches());
if (jsfunction_result_caches->length() <= cache_id) {
- __ Abort(kAttemptToUseUndefinedCache);
+ __ Abort("Attempt to use undefined cache.");
__ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
context()->Plug(v0);
return;
@@ -4063,7 +4063,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// element: Current array element.
// elements_end: Array end.
if (generate_debug_code_) {
- __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin,
+ __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin",
array_length, Operand(zero_reg));
}
__ bind(&loop);
@@ -4382,12 +4382,35 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
+ case Token::SUB:
+ EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
+ break;
+
+ case Token::BIT_NOT:
+ EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
+ break;
+
default:
UNREACHABLE();
}
}
+void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
+ const char* comment) {
+ // TODO(svenpanne): Allowing format strings in Comment would be nice here...
+ Comment cmt(masm_, comment);
+ UnaryOpStub stub(expr->op());
+ // GenericUnaryOpStub expects the argument to be in a0.
+ VisitForAccumulatorValue(expr->expression());
+ SetSourcePosition(expr->position());
+ __ mov(a0, result_register());
+ CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
+ expr->UnaryOperationFeedbackId());
+ context()->Plug(v0);
+}
+
+
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
diff --git a/chromium/v8/src/mips/lithium-codegen-mips.cc b/chromium/v8/src/mips/lithium-codegen-mips.cc
index 2bc52e4f3ff..88e7eb8f1d4 100644
--- a/chromium/v8/src/mips/lithium-codegen-mips.cc
+++ b/chromium/v8/src/mips/lithium-codegen-mips.cc
@@ -91,7 +91,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
}
-void LChunkBuilder::Abort(BailoutReason reason) {
+void LChunkBuilder::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -268,8 +268,6 @@ bool LCodeGen::GenerateBody() {
instr->Mnemonic());
}
- RecordAndUpdatePosition(instr->position());
-
instr->CompileToNative(this);
}
EnsureSpaceForLazyDeopt();
@@ -283,10 +281,6 @@ bool LCodeGen::GenerateDeferredCode() {
if (deferred_.length() > 0) {
for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
LDeferredCode* code = deferred_[i];
-
- int pos = instructions_->at(code->instruction_index())->position();
- RecordAndUpdatePosition(pos);
-
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",
code->instruction_index(),
@@ -330,7 +324,7 @@ bool LCodeGen::GenerateDeoptJumpTable() {
// end of the jump table.
if (!is_int16((masm()->pc_offset() / Assembler::kInstrSize) +
deopt_jump_table_.length() * 12)) {
- Abort(kGeneratedCodeIsTooLarge);
+ Abort("Generated code is too large");
}
if (deopt_jump_table_.length() > 0) {
@@ -417,7 +411,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
ASSERT(constant->HasSmiValue());
__ li(scratch, Operand(Smi::FromInt(constant->Integer32Value())));
} else if (r.IsDouble()) {
- Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
+ Abort("EmitLoadRegister: Unsupported double immediate.");
} else {
ASSERT(r.IsTagged());
__ LoadObject(scratch, literal);
@@ -455,9 +449,9 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
__ cvt_d_w(dbl_scratch, flt_scratch);
return dbl_scratch;
} else if (r.IsDouble()) {
- Abort(kUnsupportedDoubleImmediate);
+ Abort("unsupported double immediate");
} else if (r.IsTagged()) {
- Abort(kUnsupportedTaggedImmediate);
+ Abort("unsupported tagged immediate");
}
} else if (op->IsStackSlot() || op->IsArgument()) {
MemOperand mem_op = ToMemOperand(op);
@@ -526,14 +520,14 @@ Operand LCodeGen::ToOperand(LOperand* op) {
ASSERT(constant->HasInteger32Value());
return Operand(constant->Integer32Value());
} else if (r.IsDouble()) {
- Abort(kToOperandUnsupportedDoubleImmediate);
+ Abort("ToOperand Unsupported double immediate.");
}
ASSERT(r.IsTagged());
return Operand(constant->handle());
} else if (op->IsRegister()) {
return Operand(ToRegister(op));
} else if (op->IsDoubleRegister()) {
- Abort(kToOperandIsDoubleRegisterUnimplemented);
+ Abort("ToOperand IsDoubleRegister unimplemented");
return Operand(0);
}
// Stack slots not implemented, use ToMemOperand instead.
@@ -597,57 +591,37 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
break;
}
- int object_index = 0;
- int dematerialized_index = 0;
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
- AddToTranslation(environment,
- translation,
+
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
+ AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- &object_index,
- &dematerialized_index);
+ environment->HasUint32ValueAt(i));
}
}
-void LCodeGen::AddToTranslation(LEnvironment* environment,
- Translation* translation,
+void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer) {
- if (op == LEnvironment::materialization_marker()) {
- int object_index = (*object_index_pointer)++;
- if (environment->ObjectIsDuplicateAt(object_index)) {
- int dupe_of = environment->ObjectDuplicateOfAt(object_index);
- translation->DuplicateObject(dupe_of);
- return;
- }
- int object_length = environment->ObjectLengthAt(object_index);
- if (environment->ObjectIsArgumentsAt(object_index)) {
- translation->BeginArgumentsObject(object_length);
- } else {
- translation->BeginCapturedObject(object_length);
- }
- int dematerialized_index = *dematerialized_index_pointer;
- int env_offset = environment->translation_size() + dematerialized_index;
- *dematerialized_index_pointer += object_length;
- for (int i = 0; i < object_length; ++i) {
- LOperand* value = environment->values()->at(env_offset + i);
- AddToTranslation(environment,
- translation,
- value,
- environment->HasTaggedValueAt(env_offset + i),
- environment->HasUint32ValueAt(env_offset + i),
- object_index_pointer,
- dematerialized_index_pointer);
- }
- return;
- }
-
+ bool is_uint32) {
if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
@@ -774,7 +748,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
Address entry =
Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
if (entry == NULL) {
- Abort(kBailoutWasNotPrepared);
+ Abort("bailout was not prepared");
return;
}
@@ -787,7 +761,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
return;
}
- if (info()->ShouldTrapOnDeopt()) {
+ if (FLAG_trap_on_deopt && info()->IsOptimizing()) {
Label skip;
if (cc != al) {
__ Branch(&skip, NegateCondition(cc), src1, src2);
@@ -986,14 +960,6 @@ void LCodeGen::RecordPosition(int position) {
}
-void LCodeGen::RecordAndUpdatePosition(int position) {
- if (position >= 0 && position != old_position_) {
- masm()->positions_recorder()->RecordPosition(position);
- old_position_ = position;
- }
-}
-
-
static const char* LabelType(LLabel* label) {
if (label->is_loop_header()) return " (loop header)";
if (label->is_osr_entry()) return " (OSR entry)";
@@ -1536,11 +1502,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
__ Or(result, left, right);
break;
case Token::BIT_XOR:
- if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
- __ Nor(result, zero_reg, left);
- } else {
- __ Xor(result, left, right);
- }
+ __ Xor(result, left, right);
break;
default:
UNREACHABLE();
@@ -1801,7 +1763,7 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
__ Subu(at, at, Operand(encoding == String::ONE_BYTE_ENCODING
? one_byte_seq_type : two_byte_seq_type));
- __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
+ __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
}
__ Addu(scratch,
@@ -1818,6 +1780,13 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
}
+void LCodeGen::DoBitNotI(LBitNotI* instr) {
+ Register input = ToRegister(instr->value());
+ Register result = ToRegister(instr->result());
+ __ Nor(result, zero_reg, Operand(input));
+}
+
+
void LCodeGen::DoThrow(LThrow* instr) {
Register input_reg = EmitLoadRegister(instr->value(), at);
__ push(input_reg);
@@ -2921,6 +2890,90 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
}
+void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env) {
+ LookupResult lookup(isolate());
+ type->LookupDescriptor(NULL, *name, &lookup);
+ ASSERT(lookup.IsFound() || lookup.IsCacheable());
+ if (lookup.IsField()) {
+ int index = lookup.GetLocalFieldIndexFromMap(*type);
+ int offset = index * kPointerSize;
+ if (index < 0) {
+ // Negative property indices are in-object properties, indexed
+ // from the end of the fixed part of the object.
+ __ lw(result, FieldMemOperand(object, offset + type->instance_size()));
+ } else {
+ // Non-negative property indices are in the properties array.
+ __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ lw(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
+ }
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
+ } else {
+ // Negative lookup.
+ // Check prototypes.
+ Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
+ Heap* heap = type->GetHeap();
+ while (*current != heap->null_value()) {
+ __ LoadHeapObject(result, current);
+ __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset));
+ DeoptimizeIf(ne, env, result, Operand(Handle<Map>(current->map())));
+ current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
+ }
+ __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
+ }
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+ Register object = ToRegister(instr->object());
+ Register result = ToRegister(instr->result());
+ Register object_map = scratch0();
+
+ int map_count = instr->hydrogen()->types()->length();
+ bool need_generic = instr->hydrogen()->need_generic();
+
+ if (map_count == 0 && !need_generic) {
+ DeoptimizeIf(al, instr->environment());
+ return;
+ }
+ Handle<String> name = instr->hydrogen()->name();
+ Label done;
+ __ lw(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
+ for (int i = 0; i < map_count; ++i) {
+ bool last = (i == map_count - 1);
+ Handle<Map> map = instr->hydrogen()->types()->at(i);
+ Label check_passed;
+ __ CompareMapAndBranch(object_map, map, &check_passed, eq, &check_passed);
+ if (last && !need_generic) {
+ DeoptimizeIf(al, instr->environment());
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstantFunction(
+ result, object, map, name, instr->environment());
+ } else {
+ Label next;
+ __ Branch(&next);
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstantFunction(
+ result, object, map, name, instr->environment());
+ __ Branch(&done);
+ __ bind(&next);
+ }
+ }
+ if (need_generic) {
+ __ li(a2, Operand(name));
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ CallCode(ic, RelocInfo::CODE_TARGET, instr);
+ }
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(a0));
ASSERT(ToRegister(instr->result()).is(v0));
@@ -3016,7 +3069,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -3102,7 +3155,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -3373,7 +3426,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
void LCodeGen::DoPushArgument(LPushArgument* instr) {
LOperand* argument = instr->value();
if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
- Abort(kDoPushArgumentNotImplementedForDoubleType);
+ Abort("DoPushArgument not implemented for double type.");
} else {
Register argument_reg = EmitLoadRegister(argument, at);
__ push(argument_reg);
@@ -3592,7 +3645,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
FPURegister input = ToDoubleRegister(instr->value());
FPURegister result = ToDoubleRegister(instr->result());
__ abs_d(result, input);
- } else if (r.IsSmiOrInteger32()) {
+ } else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else {
// Representation is tagged.
@@ -4198,7 +4251,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -4276,7 +4329,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
@@ -4405,13 +4458,12 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
scratch, GetRAState(), kDontSaveFPRegs);
} else {
- PushSafepointRegistersScope scope(
- this, Safepoint::kWithRegistersAndDoubles);
+ PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
__ mov(a0, object_reg);
__ li(a1, Operand(to_map));
TransitionElementsKindStub stub(from_kind, to_kind);
__ CallStub(&stub);
- RecordSafepointWithRegistersAndDoubles(
+ RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
}
__ bind(&not_applicable);
@@ -4717,7 +4769,7 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
__ Move(reg, scratch0(), input_reg);
Label canonicalize;
__ Branch(&canonicalize, ne, scratch0(), Operand(kHoleNanUpper32));
- __ li(reg, factory()->undefined_value());
+ __ li(reg, factory()->the_hole_value());
__ Branch(&done);
__ bind(&canonicalize);
__ Move(input_reg,
@@ -5122,7 +5174,7 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
AllowDeferredHandleDereference smi_check;
if (isolate()->heap()->InNewSpace(*target)) {
Register reg = ToRegister(instr->value());
- Handle<Cell> cell = isolate()->factory()->NewCell(target);
+ Handle<Cell> cell = isolate()->factory()->NewPropertyCell(target);
__ li(at, Operand(Handle<Object>(cell)));
__ lw(at, FieldMemOperand(at, Cell::kValueOffset));
DeoptimizeIf(ne, instr->environment(), reg,
@@ -5134,63 +5186,31 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
}
-void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
- {
- PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
- __ push(object);
- CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr);
- __ StoreToSafepointRegisterSlot(v0, scratch0());
- }
- __ And(at, scratch0(), Operand(kSmiTagMask));
- DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
+void LCodeGen::DoCheckMapCommon(Register map_reg,
+ Handle<Map> map,
+ LEnvironment* env) {
+ Label success;
+ __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
+ DeoptimizeIf(al, env);
+ __ bind(&success);
}
void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
- class DeferredCheckMaps: public LDeferredCode {
- public:
- DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
- : LDeferredCode(codegen), instr_(instr), object_(object) {
- SetExit(check_maps());
- }
- virtual void Generate() {
- codegen()->DoDeferredInstanceMigration(instr_, object_);
- }
- Label* check_maps() { return &check_maps_; }
- virtual LInstruction* instr() { return instr_; }
- private:
- LCheckMaps* instr_;
- Label check_maps_;
- Register object_;
- };
-
if (instr->hydrogen()->CanOmitMapChecks()) return;
Register map_reg = scratch0();
LOperand* input = instr->value();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
+ Label success;
SmallMapList* map_set = instr->hydrogen()->map_set();
__ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-
- DeferredCheckMaps* deferred = NULL;
- if (instr->hydrogen()->has_migration_target()) {
- deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
- __ bind(deferred->check_maps());
- }
-
- Label success;
for (int i = 0; i < map_set->length() - 1; i++) {
Handle<Map> map = map_set->at(i);
__ CompareMapAndBranch(map_reg, map, &success, eq, &success);
}
Handle<Map> map = map_set->last();
- // Do the CompareMap() directly within the Branch() and DeoptimizeIf().
- if (instr->hydrogen()->has_migration_target()) {
- __ Branch(deferred->entry(), ne, map_reg, Operand(map));
- } else {
- DeoptimizeIf(ne, instr->environment(), map_reg, Operand(map));
- }
-
+ DoCheckMapCommon(map_reg, map, instr->environment());
__ bind(&success);
}
@@ -5245,6 +5265,25 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
}
+void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
+ if (instr->hydrogen()->CanOmitPrototypeChecks()) return;
+
+ Register prototype_reg = ToRegister(instr->temp());
+ Register map_reg = ToRegister(instr->temp2());
+
+ ZoneList<Handle<JSObject> >* prototypes = instr->prototypes();
+ ZoneList<Handle<Map> >* maps = instr->maps();
+
+ ASSERT(prototypes->length() == maps->length());
+
+ for (int i = 0; i < prototypes->length(); i++) {
+ __ LoadHeapObject(prototype_reg, prototypes->at(i));
+ __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
+ DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
+ }
+}
+
+
void LCodeGen::DoAllocate(LAllocate* instr) {
class DeferredAllocate: public LDeferredCode {
public:
@@ -5625,8 +5664,6 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
if (info()->IsStub() && type == Deoptimizer::EAGER) {
type = Deoptimizer::LAZY;
}
-
- Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg));
}
diff --git a/chromium/v8/src/mips/lithium-codegen-mips.h b/chromium/v8/src/mips/lithium-codegen-mips.h
index b97a3cdbaf1..a485b67db94 100644
--- a/chromium/v8/src/mips/lithium-codegen-mips.h
+++ b/chromium/v8/src/mips/lithium-codegen-mips.h
@@ -65,8 +65,7 @@ class LCodeGen BASE_EMBEDDED {
frame_is_built_(false),
safepoints_(info->zone()),
resolver_(this),
- expected_safepoint_kind_(Safepoint::kSimple),
- old_position_(RelocInfo::kNoPosition) {
+ expected_safepoint_kind_(Safepoint::kSimple) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
}
@@ -115,7 +114,7 @@ class LCodeGen BASE_EMBEDDED {
DoubleRegister EmitLoadDoubleRegister(LOperand* op,
FloatRegister flt_scratch,
DoubleRegister dbl_scratch);
- int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
+ int ToRepresentation(LConstantOperand* op, const Representation& r) const;
int32_t ToInteger32(LConstantOperand* op) const;
Smi* ToSmi(LConstantOperand* op) const;
double ToDouble(LConstantOperand* op) const;
@@ -154,7 +153,7 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
- void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
+ void DoCheckMapCommon(Register map_reg, Handle<Map> map, LEnvironment* env);
// Parallel move support.
void DoParallelMove(LParallelMove* move);
@@ -214,7 +213,7 @@ class LCodeGen BASE_EMBEDDED {
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
void FPRINTF_CHECKING Comment(const char* format, ...);
void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
@@ -291,13 +290,10 @@ class LCodeGen BASE_EMBEDDED {
Register src1 = zero_reg,
const Operand& src2 = Operand(zero_reg));
- void AddToTranslation(LEnvironment* environment,
- Translation* translation,
+ void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -323,7 +319,6 @@ class LCodeGen BASE_EMBEDDED {
int arguments,
Safepoint::DeoptMode mode);
void RecordPosition(int position);
- void RecordAndUpdatePosition(int position);
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
@@ -378,6 +373,12 @@ class LCodeGen BASE_EMBEDDED {
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp1, Register temp2);
+ void EmitLoadFieldOrConstantFunction(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env);
+
// Emits optimized code to deep-copy the contents of statically known
// object graphs (e.g. object literal boilerplate).
void EmitDeepCopy(Handle<JSObject> object,
@@ -434,8 +435,6 @@ class LCodeGen BASE_EMBEDDED {
Safepoint::Kind expected_safepoint_kind_;
- int old_position_;
-
class PushSafepointRegistersScope BASE_EMBEDDED {
public:
PushSafepointRegistersScope(LCodeGen* codegen,
diff --git a/chromium/v8/src/mips/lithium-gap-resolver-mips.cc b/chromium/v8/src/mips/lithium-gap-resolver-mips.cc
index 460e13bf0a9..771b22862ee 100644
--- a/chromium/v8/src/mips/lithium-gap-resolver-mips.cc
+++ b/chromium/v8/src/mips/lithium-gap-resolver-mips.cc
@@ -258,7 +258,7 @@ void LGapResolver::EmitMove(int index) {
} else {
__ LoadObject(dst, cgen_->ToHandle(constant_source));
}
- } else if (destination->IsDoubleRegister()) {
+ } else if (source->IsDoubleRegister()) {
DoubleRegister result = cgen_->ToDoubleRegister(destination);
double v = cgen_->ToDouble(constant_source);
__ Move(result, v);
diff --git a/chromium/v8/src/mips/lithium-mips.cc b/chromium/v8/src/mips/lithium-mips.cc
index 23f48a7709d..760be2e6e85 100644
--- a/chromium/v8/src/mips/lithium-mips.cc
+++ b/chromium/v8/src/mips/lithium-mips.cc
@@ -442,7 +442,7 @@ LPlatformChunk* LChunkBuilder::Build() {
}
-void LCodeGen::Abort(BailoutReason reason) {
+void LCodeGen::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -598,10 +598,8 @@ LInstruction* LChunkBuilder::DefineFixedDouble(
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
HEnvironment* hydrogen_env = current_block_->last_environment();
int argument_index_accumulator = 0;
- ZoneList<HValue*> objects_to_materialize(0, zone());
instr->set_environment(CreateEnvironment(hydrogen_env,
- &argument_index_accumulator,
- &objects_to_materialize));
+ &argument_index_accumulator));
return instr;
}
@@ -652,7 +650,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
- Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
+ Abort("Out of virtual registers while trying to allocate temp register.");
vreg = 0;
}
operand->set_virtual_register(vreg);
@@ -890,7 +888,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
}
#endif
- instr->set_position(position_);
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -906,13 +903,11 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LEnvironment* LChunkBuilder::CreateEnvironment(
HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize) {
+ int* argument_index_accumulator) {
if (hydrogen_env == NULL) return NULL;
- LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
- argument_index_accumulator,
- objects_to_materialize);
+ LEnvironment* outer =
+ CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
@@ -927,16 +922,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- int object_index = objects_to_materialize->length();
for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
- LOperand* op;
HValue* value = hydrogen_env->values()->at(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
+ LOperand* op = NULL;
+ if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
+ op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
} else {
@@ -947,33 +942,15 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
value->CheckFlag(HInstruction::kUint32));
}
- for (int i = object_index; i < objects_to_materialize->length(); ++i) {
- HValue* object_to_materialize = objects_to_materialize->at(i);
- int previously_materialized_object = -1;
- for (int prev = 0; prev < i; ++prev) {
- if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
- previously_materialized_object = prev;
- break;
- }
- }
- int length = object_to_materialize->OperandCount();
- bool is_arguments = object_to_materialize->IsArgumentsObject();
- if (previously_materialized_object >= 0) {
- result->AddDuplicateObject(previously_materialized_object);
- continue;
- } else {
- result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
- }
- for (int i = is_arguments ? 1 : 0; i < length; ++i) {
- LOperand* op;
- HValue* value = object_to_materialize->OperandAt(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
- } else {
- ASSERT(!value->IsPushArgument());
- op = UseAny(value);
- }
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ LOperand* op = UseAny(value);
result->AddValue(op,
value->representation(),
value->CheckFlag(HInstruction::kUint32));
@@ -1350,6 +1327,15 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
}
+LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
+ ASSERT(instr->value()->representation().IsInteger32());
+ ASSERT(instr->representation().IsInteger32());
+ if (instr->HasNoUses()) return NULL;
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new(zone()) LBitNotI(value));
+}
+
+
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
@@ -1628,8 +1614,9 @@ LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(r));
- ASSERT(instr->right()->representation().Equals(r));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->left()->representation().Equals(
+ instr->right()->representation()));
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
return new(zone()) LCompareNumericAndBranch(left, right);
@@ -1764,6 +1751,17 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
+LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
+ return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
@@ -1937,6 +1935,19 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
}
+LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
+ LUnallocated* temp1 = NULL;
+ LOperand* temp2 = NULL;
+ if (!instr->CanOmitPrototypeChecks()) {
+ temp1 = TempRegister();
+ temp2 = TempRegister();
+ }
+ LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
+ if (instr->CanOmitPrototypeChecks()) return result;
+ return AssignEnvironment(result);
+}
+
+
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckFunction(value));
@@ -1945,16 +1956,10 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
LOperand* value = NULL;
- if (!instr->CanOmitMapChecks()) {
- value = UseRegisterAtStart(instr->value());
- if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
- }
- LCheckMaps* result = new(zone()) LCheckMaps(value);
- if (!instr->CanOmitMapChecks()) {
- AssignEnvironment(result);
- if (instr->has_migration_target()) return AssignPointerMap(result);
- }
- return result;
+ if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
+ LInstruction* result = new(zone()) LCheckMaps(value);
+ if (instr->CanOmitMapChecks()) return result;
+ return AssignEnvironment(result);
}
@@ -2066,6 +2071,23 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
}
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+ HLoadNamedFieldPolymorphic* instr) {
+ ASSERT(instr->representation().IsTagged());
+ if (instr->need_generic()) {
+ LOperand* obj = UseFixed(instr->object(), a0);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
+ return MarkAsCall(DefineFixed(result, v0), instr);
+ } else {
+ LOperand* obj = UseRegisterAtStart(instr->object());
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
+ return AssignEnvironment(DefineAsRegister(result));
+ }
+}
+
+
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), a0);
LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), v0);
@@ -2221,7 +2243,7 @@ LInstruction* LChunkBuilder::DoTrapAllocationMemento(
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool is_in_object = instr->access().IsInobject();
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
+ bool needs_write_barrier_for_map = !instr->transition().is_null() &&
instr->NeedsWriteBarrierForMap();
LOperand* obj;
@@ -2341,7 +2363,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
- Abort(kTooManySpillSlotsNeededForOSR);
+ Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
@@ -2363,12 +2385,6 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
}
-LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
- // There are no real uses of a captured object.
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
info()->MarkAsRequiresFrame();
LOperand* args = UseRegister(instr->arguments());
diff --git a/chromium/v8/src/mips/lithium-mips.h b/chromium/v8/src/mips/lithium-mips.h
index a1792b17b22..44c909ea766 100644
--- a/chromium/v8/src/mips/lithium-mips.h
+++ b/chromium/v8/src/mips/lithium-mips.h
@@ -50,6 +50,7 @@ class LCodeGen;
V(ArithmeticD) \
V(ArithmeticT) \
V(BitI) \
+ V(BitNotI) \
V(BoundsCheck) \
V(Branch) \
V(CallConstantFunction) \
@@ -67,6 +68,7 @@ class LCodeGen;
V(CheckMaps) \
V(CheckMapValue) \
V(CheckNonSmi) \
+ V(CheckPrototypeMaps) \
V(CheckSmi) \
V(ClampDToUint8) \
V(ClampIToUint8) \
@@ -126,6 +128,7 @@ class LCodeGen;
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
+ V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -204,12 +207,9 @@ class LCodeGen;
class LInstruction: public ZoneObject {
public:
LInstruction()
- : environment_(NULL),
- hydrogen_value_(NULL),
- bit_field_(IsCallBits::encode(false)) {
- set_position(RelocInfo::kNoPosition);
- }
-
+ : environment_(NULL),
+ hydrogen_value_(NULL),
+ is_call_(false) { }
virtual ~LInstruction() { }
virtual void CompileToNative(LCodeGen* generator) = 0;
@@ -248,30 +248,20 @@ class LInstruction: public ZoneObject {
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
- // The 31 bits PositionBits is used to store the int position value. And the
- // position value may be RelocInfo::kNoPosition (-1). The accessor always
- // +1/-1 so that the encoded value of position in bit_field_ is always >= 0
- // and can fit into the 31 bits PositionBits.
- void set_position(int pos) {
- bit_field_ = PositionBits::update(bit_field_, pos + 1);
- }
- int position() { return PositionBits::decode(bit_field_) - 1; }
-
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
- void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
- bool IsCall() const { return IsCallBits::decode(bit_field_); }
+ void MarkAsCall() { is_call_ = true; }
// Interface to the register allocator and iterators.
- bool ClobbersTemps() const { return IsCall(); }
- bool ClobbersRegisters() const { return IsCall(); }
- bool ClobbersDoubleRegisters() const { return IsCall(); }
+ bool ClobbersTemps() const { return is_call_; }
+ bool ClobbersRegisters() const { return is_call_; }
+ bool ClobbersDoubleRegisters() const { return is_call_; }
// Interface to the register allocator and iterators.
- bool IsMarkedAsCall() const { return IsCall(); }
+ bool IsMarkedAsCall() const { return is_call_; }
virtual bool HasResult() const = 0;
virtual LOperand* result() const = 0;
@@ -295,13 +285,10 @@ class LInstruction: public ZoneObject {
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
- class IsCallBits: public BitField<bool, 0, 1> {};
- class PositionBits: public BitField<int, 1, 31> {};
-
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
- int bit_field_;
+ bool is_call_;
};
@@ -1369,6 +1356,18 @@ class LThrow: public LTemplateInstruction<0, 1, 0> {
};
+class LBitNotI: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LBitNotI(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ LOperand* value() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
+};
+
+
class LAddI: public LTemplateInstruction<1, 2, 0> {
public:
LAddI(LOperand* left, LOperand* right) {
@@ -1504,6 +1503,19 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
};
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ LOperand* object() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+ DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+};
+
+
class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadNamedGeneric(LOperand* object) {
@@ -2116,7 +2128,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
virtual void PrintDataTo(StringStream* stream);
- Handle<Map> transition() const { return hydrogen()->transition_map(); }
+ Handle<Map> transition() const { return hydrogen()->transition(); }
Representation representation() const {
return hydrogen()->field_representation();
}
@@ -2312,6 +2324,26 @@ class LCheckMaps: public LTemplateInstruction<0, 1, 0> {
};
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 2> {
+ public:
+ LCheckPrototypeMaps(LOperand* temp, LOperand* temp2) {
+ temps_[0] = temp;
+ temps_[1] = temp2;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+ LOperand* temp2() { return temps_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
+ DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
+
+ ZoneList<Handle<JSObject> >* prototypes() const {
+ return hydrogen()->prototypes();
+ }
+ ZoneList<Handle<Map> >* maps() const { return hydrogen()->maps(); }
+};
+
+
class LCheckSmi: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCheckSmi(LOperand* value) {
@@ -2610,7 +2642,7 @@ class LChunkBuilder BASE_EMBEDDED {
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
// Methods for getting operands for Use / Define / Temp.
LUnallocated* ToUnallocated(Register reg);
@@ -2692,8 +2724,7 @@ class LChunkBuilder BASE_EMBEDDED {
CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize);
+ int* argument_index_accumulator);
void VisitInstruction(HInstruction* current);
diff --git a/chromium/v8/src/mips/macro-assembler-mips.cc b/chromium/v8/src/mips/macro-assembler-mips.cc
index e53f10afaca..ea08a552be5 100644
--- a/chromium/v8/src/mips/macro-assembler-mips.cc
+++ b/chromium/v8/src/mips/macro-assembler-mips.cc
@@ -256,7 +256,7 @@ void MacroAssembler::RecordWrite(Register object,
if (emit_debug_code()) {
lw(at, MemOperand(address));
Assert(
- eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value));
+ eq, "Wrong address or value passed to RecordWrite", at, Operand(value));
}
Label done;
@@ -358,7 +358,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
// In debug mode, make sure the lexical context is set.
#ifdef DEBUG
- Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
+ Check(ne, "we should not have an empty lexical context",
scratch, Operand(zero_reg));
#endif
@@ -374,7 +374,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// Read the first word and compare to the native_context_map.
lw(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
LoadRoot(at, Heap::kNativeContextMapRootIndex);
- Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
+ Check(eq, "JSGlobalObject::native_context should be a native context.",
holder_reg, Operand(at));
pop(holder_reg); // Restore holder.
}
@@ -388,12 +388,12 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
push(holder_reg); // Temporarily save holder on the stack.
mov(holder_reg, at); // Move at to its holding place.
LoadRoot(at, Heap::kNullValueRootIndex);
- Check(ne, kJSGlobalProxyContextShouldNotBeNull,
+ Check(ne, "JSGlobalProxy::context() should not be null.",
holder_reg, Operand(at));
lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
LoadRoot(at, Heap::kNativeContextMapRootIndex);
- Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
+ Check(eq, "JSGlobalObject::native_context should be a native context.",
holder_reg, Operand(at));
// Restore at is not needed. at is reloaded below.
pop(holder_reg); // Restore holder.
@@ -2923,7 +2923,9 @@ void MacroAssembler::Allocate(int object_size,
// Set up allocation top address and object size registers.
Register topaddr = scratch1;
+ Register obj_size_reg = scratch2;
li(topaddr, Operand(allocation_top));
+ li(obj_size_reg, Operand(object_size));
// This code stores a temporary value in t9.
if ((flags & RESULT_CONTAINS_TOP) == 0) {
@@ -2936,29 +2938,15 @@ void MacroAssembler::Allocate(int object_size,
// immediately below so this use of t9 does not cause difference with
// respect to register content between debug and release mode.
lw(t9, MemOperand(topaddr));
- Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
+ Check(eq, "Unexpected allocation top", result, Operand(t9));
}
// Load allocation limit into t9. Result already contains allocation top.
lw(t9, MemOperand(topaddr, limit - top));
}
- 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));
- Label aligned;
- Branch(&aligned, eq, scratch2, Operand(zero_reg));
- li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
- sw(scratch2, MemOperand(result));
- Addu(result, result, Operand(kDoubleSize / 2));
- bind(&aligned);
- }
-
// Calculate new top and bail out if new space is exhausted. Use result
// to calculate the new top.
- Addu(scratch2, result, Operand(object_size));
+ Addu(scratch2, result, Operand(obj_size_reg));
Branch(gc_required, Ugreater, scratch2, Operand(t9));
sw(scratch2, MemOperand(topaddr));
@@ -3020,26 +3008,12 @@ void MacroAssembler::Allocate(Register object_size,
// immediately below so this use of t9 does not cause difference with
// respect to register content between debug and release mode.
lw(t9, MemOperand(topaddr));
- Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
+ Check(eq, "Unexpected allocation top", result, Operand(t9));
}
// Load allocation limit into t9. Result already contains allocation top.
lw(t9, MemOperand(topaddr, limit - top));
}
- 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));
- Label aligned;
- Branch(&aligned, eq, scratch2, Operand(zero_reg));
- li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
- sw(scratch2, MemOperand(result));
- Addu(result, result, Operand(kDoubleSize / 2));
- bind(&aligned);
- }
-
// Calculate new top and bail out if new space is exhausted. Use result
// to calculate the new top. Object size may be in words so a shift is
// required to get the number of bytes.
@@ -3054,7 +3028,7 @@ void MacroAssembler::Allocate(Register object_size,
// Update allocation top. result temporarily holds the new top.
if (emit_debug_code()) {
And(t9, scratch2, Operand(kObjectAlignmentMask));
- Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg));
+ Check(eq, "Unaligned allocation in new space", t9, Operand(zero_reg));
}
sw(scratch2, MemOperand(topaddr));
@@ -3076,7 +3050,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object,
// Check that the object un-allocated is below the current top.
li(scratch, Operand(new_space_allocation_top));
lw(scratch, MemOperand(scratch));
- Check(less, kUndoAllocationOfNonAllocatedMemory,
+ Check(less, "Undo allocation of non allocated memory",
object, Operand(scratch));
#endif
// Write the address of the object to un-allocate as the current top.
@@ -3329,7 +3303,7 @@ void MacroAssembler::CopyBytes(Register src,
bind(&word_loop);
if (emit_debug_code()) {
And(scratch, src, kPointerSize - 1);
- Assert(eq, kExpectingAlignmentForCopyBytes,
+ Assert(eq, "Expecting alignment for CopyBytes",
scratch, Operand(zero_reg));
}
Branch(&byte_loop, lt, length, Operand(kPointerSize));
@@ -4055,7 +4029,7 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
sw(s0, MemOperand(s3, kNextOffset));
if (emit_debug_code()) {
lw(a1, MemOperand(s3, kLevelOffset));
- Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2));
+ Check(eq, "Unexpected level after return from api call", a1, Operand(s2));
}
Subu(s2, s2, Operand(1));
sw(s2, MemOperand(s3, kLevelOffset));
@@ -4409,10 +4383,10 @@ void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
// -----------------------------------------------------------------------------
// Debugging.
-void MacroAssembler::Assert(Condition cc, BailoutReason reason,
+void MacroAssembler::Assert(Condition cc, const char* msg,
Register rs, Operand rt) {
if (emit_debug_code())
- Check(cc, reason, rs, rt);
+ Check(cc, msg, rs, rt);
}
@@ -4420,7 +4394,7 @@ void MacroAssembler::AssertRegisterIsRoot(Register reg,
Heap::RootListIndex index) {
if (emit_debug_code()) {
LoadRoot(at, index);
- Check(eq, kRegisterDidNotMatchExpectedRoot, reg, Operand(at));
+ Check(eq, "Register did not match expected root", reg, Operand(at));
}
}
@@ -4437,24 +4411,24 @@ void MacroAssembler::AssertFastElements(Register elements) {
Branch(&ok, eq, elements, Operand(at));
LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
Branch(&ok, eq, elements, Operand(at));
- Abort(kJSObjectWithFastElementsMapHasSlowElements);
+ Abort("JSObject with fast elements map has slow elements");
bind(&ok);
pop(elements);
}
}
-void MacroAssembler::Check(Condition cc, BailoutReason reason,
+void MacroAssembler::Check(Condition cc, const char* msg,
Register rs, Operand rt) {
Label L;
Branch(&L, cc, rs, rt);
- Abort(reason);
+ Abort(msg);
// Will not return here.
bind(&L);
}
-void MacroAssembler::Abort(BailoutReason reason) {
+void MacroAssembler::Abort(const char* msg) {
Label abort_start;
bind(&abort_start);
// We want to pass the msg string like a smi to avoid GC
@@ -4462,7 +4436,6 @@ void MacroAssembler::Abort(BailoutReason reason) {
// properly. Instead, we pass an aligned pointer that is
// a proper v8 smi, but also pass the alignment difference
// from the real pointer as a smi.
- const char* msg = GetBailoutReason(reason);
intptr_t p1 = reinterpret_cast<intptr_t>(msg);
intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
@@ -4606,7 +4579,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
Branch(&ok);
bind(&fail);
- Abort(kGlobalFunctionsMustHaveInitialMap);
+ Abort("Global functions must have initial map");
bind(&ok);
}
}
@@ -4889,7 +4862,7 @@ void MacroAssembler::AssertNotSmi(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
andi(at, object, kSmiTagMask);
- Check(ne, kOperandIsASmi, at, Operand(zero_reg));
+ Check(ne, "Operand is a smi", at, Operand(zero_reg));
}
}
@@ -4898,7 +4871,7 @@ void MacroAssembler::AssertSmi(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
andi(at, object, kSmiTagMask);
- Check(eq, kOperandIsASmi, at, Operand(zero_reg));
+ Check(eq, "Operand is a smi", at, Operand(zero_reg));
}
}
@@ -4907,11 +4880,11 @@ void MacroAssembler::AssertString(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
And(t0, object, Operand(kSmiTagMask));
- Check(ne, kOperandIsASmiAndNotAString, t0, Operand(zero_reg));
+ Check(ne, "Operand is a smi and not a string", t0, Operand(zero_reg));
push(object);
lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
- Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE));
+ Check(lo, "Operand is not a string", object, Operand(FIRST_NONSTRING_TYPE));
pop(object);
}
}
@@ -4921,11 +4894,11 @@ void MacroAssembler::AssertName(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
And(t0, object, Operand(kSmiTagMask));
- Check(ne, kOperandIsASmiAndNotAName, t0, Operand(zero_reg));
+ Check(ne, "Operand is a smi and not a name", t0, Operand(zero_reg));
push(object);
lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
- Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE));
+ Check(le, "Operand is not a name", object, Operand(LAST_NAME_TYPE));
pop(object);
}
}
@@ -4933,11 +4906,11 @@ void MacroAssembler::AssertName(Register object) {
void MacroAssembler::AssertRootValue(Register src,
Heap::RootListIndex root_value_index,
- BailoutReason reason) {
+ const char* message) {
if (emit_debug_code()) {
ASSERT(!src.is(at));
LoadRoot(at, root_value_index);
- Check(eq, reason, src, Operand(at));
+ Check(eq, message, src, Operand(at));
}
}
@@ -5154,7 +5127,7 @@ void MacroAssembler::PatchRelocatedValue(Register li_location,
// At this point scratch is a lui(at, ...) instruction.
if (emit_debug_code()) {
And(scratch, scratch, kOpcodeMask);
- Check(eq, kTheInstructionToPatchShouldBeALui,
+ Check(eq, "The instruction to patch should be a lui.",
scratch, Operand(LUI));
lw(scratch, MemOperand(li_location));
}
@@ -5166,7 +5139,7 @@ void MacroAssembler::PatchRelocatedValue(Register li_location,
// scratch is now ori(at, ...).
if (emit_debug_code()) {
And(scratch, scratch, kOpcodeMask);
- Check(eq, kTheInstructionToPatchShouldBeAnOri,
+ Check(eq, "The instruction to patch should be an ori.",
scratch, Operand(ORI));
lw(scratch, MemOperand(li_location, kInstrSize));
}
@@ -5183,7 +5156,7 @@ void MacroAssembler::GetRelocatedValue(Register li_location,
lw(value, MemOperand(li_location));
if (emit_debug_code()) {
And(value, value, kOpcodeMask);
- Check(eq, kTheInstructionShouldBeALui,
+ Check(eq, "The instruction should be a lui.",
value, Operand(LUI));
lw(value, MemOperand(li_location));
}
@@ -5194,7 +5167,7 @@ void MacroAssembler::GetRelocatedValue(Register li_location,
lw(scratch, MemOperand(li_location, kInstrSize));
if (emit_debug_code()) {
And(scratch, scratch, kOpcodeMask);
- Check(eq, kTheInstructionShouldBeAnOri,
+ Check(eq, "The instruction should be an ori.",
scratch, Operand(ORI));
lw(scratch, MemOperand(li_location, kInstrSize));
}
diff --git a/chromium/v8/src/mips/macro-assembler-mips.h b/chromium/v8/src/mips/macro-assembler-mips.h
index 61a0c3a228f..bc3e7c48b4a 100644
--- a/chromium/v8/src/mips/macro-assembler-mips.h
+++ b/chromium/v8/src/mips/macro-assembler-mips.h
@@ -51,6 +51,20 @@ class JumpTarget;
// MIPS generated code calls C code, it must be via t9 register.
+// Flags used for the AllocateInNewSpace functions.
+enum AllocationFlags {
+ // No special flags.
+ NO_ALLOCATION_FLAGS = 0,
+ // Return the pointer to the allocated already tagged as a heap object.
+ TAG_OBJECT = 1 << 0,
+ // The content of the result register already contains the allocation top in
+ // new space.
+ RESULT_CONTAINS_TOP = 1 << 1,
+ // Specify that the requested size of the space to allocate is specified in
+ // words instead of bytes.
+ SIZE_IN_WORDS = 1 << 2
+};
+
// Flags used for AllocateHeapNumber
enum TaggingMode {
// Tag the result.
@@ -613,11 +627,11 @@ class MacroAssembler: public Assembler {
void MultiPushFPU(RegList regs);
void MultiPushReversedFPU(RegList regs);
+ // Lower case push() for compatibility with arch-independent code.
void push(Register src) {
Addu(sp, sp, Operand(-kPointerSize));
sw(src, MemOperand(sp, 0));
}
- void Push(Register src) { push(src); }
// Push a handle.
void Push(Handle<Object> handle);
@@ -662,11 +676,11 @@ class MacroAssembler: public Assembler {
void MultiPopFPU(RegList regs);
void MultiPopReversedFPU(RegList regs);
+ // Lower case pop() for compatibility with arch-independent code.
void pop(Register dst) {
lw(dst, MemOperand(sp, 0));
Addu(sp, sp, Operand(kPointerSize));
}
- void Pop(Register dst) { pop(dst); }
// Pop two registers. Pops rightmost register first (from lower address).
void Pop(Register src1, Register src2) {
@@ -1272,15 +1286,15 @@ class MacroAssembler: public Assembler {
// Calls Abort(msg) if the condition cc is not satisfied.
// Use --debug_code to enable.
- void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt);
+ void Assert(Condition cc, const char* msg, Register rs, Operand rt);
void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
void AssertFastElements(Register elements);
// Like Assert(), but always enabled.
- void Check(Condition cc, BailoutReason reason, Register rs, Operand rt);
+ void Check(Condition cc, const char* msg, Register rs, Operand rt);
// Print a message to stdout and abort execution.
- void Abort(BailoutReason msg);
+ void Abort(const char* msg);
// Verify restrictions about code generated in stubs.
void set_generating_stub(bool value) { generating_stub_ = value; }
@@ -1364,7 +1378,7 @@ class MacroAssembler: public Assembler {
// enabled via --debug-code.
void AssertRootValue(Register src,
Heap::RootListIndex root_value_index,
- BailoutReason reason);
+ const char* message);
// ---------------------------------------------------------------------------
// HeapNumber utilities.
diff --git a/chromium/v8/src/object-observe.js b/chromium/v8/src/object-observe.js
index f5e0d9d563a..a5c12bf0098 100644
--- a/chromium/v8/src/object-observe.js
+++ b/chromium/v8/src/object-observe.js
@@ -394,10 +394,7 @@ function ObjectGetNotifier(object) {
if (ObjectIsFrozen(object)) return null;
var objectInfo = objectInfoMap.get(object);
- if (IS_UNDEFINED(objectInfo)) {
- objectInfo = CreateObjectInfo(object);
- %SetIsObserved(object);
- }
+ if (IS_UNDEFINED(objectInfo)) objectInfo = CreateObjectInfo(object);
if (IS_NULL(objectInfo.notifier)) {
objectInfo.notifier = { __proto__: notifierPrototype };
diff --git a/chromium/v8/src/objects-debug.cc b/chromium/v8/src/objects-debug.cc
index e0cb8c92948..395f95ca7ea 100644
--- a/chromium/v8/src/objects-debug.cc
+++ b/chromium/v8/src/objects-debug.cc
@@ -366,12 +366,9 @@ void Map::SharedMapVerify() {
}
-void Map::VerifyOmittedMapChecks() {
- if (!FLAG_omit_map_checks_for_leaf_maps) return;
- if (!is_stable() ||
- is_deprecated() ||
- HasTransitionArray() ||
- is_dictionary_map()) {
+void Map::VerifyOmittedPrototypeChecks() {
+ if (!FLAG_omit_prototype_checks_for_leaf_maps) return;
+ if (HasTransitionArray() || is_dictionary_map()) {
CHECK_EQ(0, dependent_code()->number_of_entries(
DependentCode::kPrototypeCheckGroup));
}
diff --git a/chromium/v8/src/objects-inl.h b/chromium/v8/src/objects-inl.h
index 169475791d0..128dc6be281 100644
--- a/chromium/v8/src/objects-inl.h
+++ b/chromium/v8/src/objects-inl.h
@@ -3617,17 +3617,6 @@ bool Map::is_deprecated() {
}
-void Map::set_migration_target(bool value) {
- set_bit_field3(IsMigrationTarget::update(bit_field3(), value));
-}
-
-
-bool Map::is_migration_target() {
- if (!FLAG_track_fields) return false;
- return IsMigrationTarget::decode(bit_field3());
-}
-
-
void Map::freeze() {
set_bit_field3(IsFrozen::update(bit_field3(), true));
}
@@ -3688,6 +3677,11 @@ void Map::NotifyLeafMapLayoutChange() {
}
+bool Map::CanOmitPrototypeChecks() {
+ return is_stable() && FLAG_omit_prototype_checks_for_leaf_maps;
+}
+
+
bool Map::CanOmitMapChecks() {
return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
}
@@ -3822,6 +3816,7 @@ inline void Code::set_is_crankshafted(bool value) {
int Code::major_key() {
ASSERT(kind() == STUB ||
+ kind() == UNARY_OP_IC ||
kind() == BINARY_OP_IC ||
kind() == COMPARE_IC ||
kind() == COMPARE_NIL_IC ||
@@ -3836,6 +3831,7 @@ int Code::major_key() {
void Code::set_major_key(int major) {
ASSERT(kind() == STUB ||
+ kind() == UNARY_OP_IC ||
kind() == BINARY_OP_IC ||
kind() == COMPARE_IC ||
kind() == COMPARE_NIL_IC ||
@@ -4025,6 +4021,21 @@ void Code::set_check_type(CheckType value) {
}
+byte Code::unary_op_type() {
+ ASSERT(is_unary_op_stub());
+ return UnaryOpTypeField::decode(
+ READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
+}
+
+
+void Code::set_unary_op_type(byte value) {
+ ASSERT(is_unary_op_stub());
+ int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
+ int updated = UnaryOpTypeField::update(previous, value);
+ WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
+}
+
+
byte Code::to_boolean_state() {
return extended_extra_ic_state();
}
@@ -4209,20 +4220,7 @@ void Map::InitializeDescriptors(DescriptorArray* descriptors) {
ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
-
-
-void Map::set_bit_field3(uint32_t bits) {
- // Ensure the upper 2 bits have the same value by sign extending it. This is
- // necessary to be able to use the 31st bit.
- int value = bits << 1;
- WRITE_FIELD(this, kBitField3Offset, Smi::FromInt(value >> 1));
-}
-
-
-uint32_t Map::bit_field3() {
- Object* value = READ_FIELD(this, kBitField3Offset);
- return Smi::cast(value)->value();
-}
+SMI_ACCESSORS(Map, bit_field3, kBitField3Offset)
void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
diff --git a/chromium/v8/src/objects-printer.cc b/chromium/v8/src/objects-printer.cc
index 7b6f7a478ce..87b2811e413 100644
--- a/chromium/v8/src/objects-printer.cc
+++ b/chromium/v8/src/objects-printer.cc
@@ -37,6 +37,9 @@ namespace internal {
#ifdef OBJECT_PRINT
+static const char* TypeToString(InstanceType type);
+
+
void MaybeObject::Print() {
Print(stdout);
}
@@ -506,12 +509,83 @@ void JSModule::JSModulePrint(FILE* out) {
static const char* TypeToString(InstanceType type) {
switch (type) {
-#define TYPE_TO_STRING(TYPE) case TYPE: return #TYPE;
- INSTANCE_TYPE_LIST(TYPE_TO_STRING)
-#undef TYPE_TO_STRING
+ case INVALID_TYPE: return "INVALID";
+ case MAP_TYPE: return "MAP";
+ case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
+ case SYMBOL_TYPE: return "SYMBOL";
+ case STRING_TYPE: return "TWO_BYTE_STRING";
+ case ASCII_STRING_TYPE: return "ASCII_STRING";
+ case CONS_STRING_TYPE:
+ case CONS_ASCII_STRING_TYPE:
+ return "CONS_STRING";
+ case EXTERNAL_STRING_TYPE:
+ case EXTERNAL_ASCII_STRING_TYPE:
+ case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
+ return "EXTERNAL_STRING";
+ case SHORT_EXTERNAL_STRING_TYPE:
+ case SHORT_EXTERNAL_ASCII_STRING_TYPE:
+ case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
+ return "SHORT_EXTERNAL_STRING";
+ case INTERNALIZED_STRING_TYPE: return "INTERNALIZED_STRING";
+ case ASCII_INTERNALIZED_STRING_TYPE: return "ASCII_INTERNALIZED_STRING";
+ case CONS_INTERNALIZED_STRING_TYPE: return "CONS_INTERNALIZED_STRING";
+ case CONS_ASCII_INTERNALIZED_STRING_TYPE:
+ return "CONS_ASCII_INTERNALIZED_STRING";
+ case EXTERNAL_INTERNALIZED_STRING_TYPE:
+ case EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE:
+ case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
+ return "EXTERNAL_INTERNALIZED_STRING";
+ case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE:
+ case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE:
+ case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
+ return "SHORT_EXTERNAL_INTERNALIZED_STRING";
+ case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
+ case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
+ case FREE_SPACE_TYPE: return "FREE_SPACE";
+ case EXTERNAL_PIXEL_ARRAY_TYPE: return "EXTERNAL_PIXEL_ARRAY";
+ case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
+ case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+ return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
+ case EXTERNAL_SHORT_ARRAY_TYPE: return "EXTERNAL_SHORT_ARRAY";
+ case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+ return "EXTERNAL_UNSIGNED_SHORT_ARRAY";
+ case EXTERNAL_INT_ARRAY_TYPE: return "EXTERNAL_INT_ARRAY";
+ case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+ return "EXTERNAL_UNSIGNED_INT_ARRAY";
+ case EXTERNAL_FLOAT_ARRAY_TYPE: return "EXTERNAL_FLOAT_ARRAY";
+ case EXTERNAL_DOUBLE_ARRAY_TYPE: return "EXTERNAL_DOUBLE_ARRAY";
+ case FILLER_TYPE: return "FILLER";
+ case JS_OBJECT_TYPE: return "JS_OBJECT";
+ case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
+ case ODDBALL_TYPE: return "ODDBALL";
+ case CELL_TYPE: return "CELL";
+ case PROPERTY_CELL_TYPE: return "PROPERTY_CELL";
+ case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
+ case JS_GENERATOR_OBJECT_TYPE: return "JS_GENERATOR_OBJECT";
+ case JS_MODULE_TYPE: return "JS_MODULE";
+ case JS_FUNCTION_TYPE: return "JS_FUNCTION";
+ case CODE_TYPE: return "CODE";
+ case JS_ARRAY_TYPE: return "JS_ARRAY";
+ case JS_PROXY_TYPE: return "JS_PROXY";
+ case JS_SET_TYPE: return "JS_SET";
+ case JS_MAP_TYPE: return "JS_MAP";
+ case JS_WEAK_MAP_TYPE: return "JS_WEAK_MAP";
+ case JS_WEAK_SET_TYPE: return "JS_WEAK_SET";
+ case JS_REGEXP_TYPE: return "JS_REGEXP";
+ case JS_VALUE_TYPE: return "JS_VALUE";
+ case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
+ case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
+ case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
+ case JS_ARRAY_BUFFER_TYPE: return "JS_ARRAY_BUFFER";
+ case JS_TYPED_ARRAY_TYPE: return "JS_TYPED_ARRAY";
+ case JS_DATA_VIEW_TYPE: return "JS_DATA_VIEW";
+ case FOREIGN_TYPE: return "FOREIGN";
+ case JS_MESSAGE_OBJECT_TYPE: return "JS_MESSAGE_OBJECT_TYPE";
+#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
+ STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+ default: return "UNKNOWN";
}
- UNREACHABLE();
- return "UNKNOWN"; // Keep the compiler happy.
}
diff --git a/chromium/v8/src/objects-visiting.h b/chromium/v8/src/objects-visiting.h
index 21757377a4f..32e457b869a 100644
--- a/chromium/v8/src/objects-visiting.h
+++ b/chromium/v8/src/objects-visiting.h
@@ -141,7 +141,7 @@ class StaticVisitorBase : public AllStatic {
(base == kVisitJSObject));
ASSERT(IsAligned(object_size, kPointerSize));
ASSERT(kMinObjectSizeInWords * kPointerSize <= object_size);
- ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
+ ASSERT(object_size < Page::kMaxNonCodeHeapObjectSize);
const VisitorId specialization = static_cast<VisitorId>(
base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords);
diff --git a/chromium/v8/src/objects.cc b/chromium/v8/src/objects.cc
index 995ed36f022..2e9badbb2aa 100644
--- a/chromium/v8/src/objects.cc
+++ b/chromium/v8/src/objects.cc
@@ -2719,7 +2719,6 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
Handle<Map>(new_map);
return maybe_map;
}
- new_map->set_migration_target(true);
}
new_map->set_owns_descriptors(true);
@@ -6518,7 +6517,6 @@ MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
result->set_dictionary_map(true);
- result->set_migration_target(false);
#ifdef VERIFY_HEAP
if (FLAG_verify_heap && result->is_shared()) {
@@ -9222,7 +9220,6 @@ void JSFunction::MarkForLazyRecompilation() {
ASSERT(!IsOptimized());
ASSERT(shared()->allows_lazy_compilation() ||
code()->optimizable());
- ASSERT(!shared()->is_generator());
set_code_no_write_barrier(
GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile));
// No write barrier required, since the builtin is part of the root set.
@@ -9233,8 +9230,10 @@ void JSFunction::MarkForParallelRecompilation() {
ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
ASSERT(!IsOptimized());
ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
- ASSERT(!shared()->is_generator());
- ASSERT(FLAG_parallel_recompilation);
+ if (!FLAG_parallel_recompilation) {
+ JSFunction::MarkForLazyRecompilation();
+ return;
+ }
if (FLAG_trace_parallel_recompilation) {
PrintF(" ** Marking ");
PrintName();
@@ -9805,7 +9804,7 @@ void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
}
-void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
+void SharedFunctionInfo::DisableOptimization(const char* reason) {
// Disable optimization for the shared function info and mark the
// code as non-optimizable. The marker on the shared function info
// is there because we flush non-optimized code thereby loosing the
@@ -9823,7 +9822,7 @@ void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
if (FLAG_trace_opt) {
PrintF("[disabled optimization for ");
ShortPrint();
- PrintF(", reason: %s]\n", GetBailoutReason(reason));
+ PrintF(", reason: %s]\n", reason);
}
}
@@ -10636,14 +10635,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
break;
}
- case Translation::DUPLICATED_OBJECT: {
- int object_index = iterator.Next();
- PrintF(out, "{object_index=%d}", object_index);
- break;
- }
-
- case Translation::ARGUMENTS_OBJECT:
- case Translation::CAPTURED_OBJECT: {
+ case Translation::ARGUMENTS_OBJECT: {
int args_length = iterator.Next();
PrintF(out, "{length=%d}", args_length);
break;
@@ -10801,17 +10793,18 @@ void Code::Disassemble(const char* name, FILE* out) {
// If there is no back edge table, the "table start" will be at or after
// (due to alignment) the end of the instruction stream.
if (static_cast<int>(offset) < instruction_size()) {
- FullCodeGenerator::BackEdgeTableIterator back_edges(this);
-
- PrintF(out, "Back edges (size = %u)\n", back_edges.table_length());
+ Address back_edge_cursor = instruction_start() + offset;
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor);
+ PrintF(out, "Back edges (size = %u)\n", table_length);
PrintF(out, "ast_id pc_offset loop_depth\n");
-
- for ( ; !back_edges.Done(); back_edges.Next()) {
- PrintF(out, "%6d %9u %10u\n", back_edges.ast_id().ToInt(),
- back_edges.pc_offset(),
- back_edges.loop_depth());
+ for (uint32_t i = 0; i < table_length; ++i) {
+ uint32_t ast_id = Memory::uint32_at(back_edge_cursor);
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize);
+ uint32_t loop_depth = Memory::uint32_at(back_edge_cursor +
+ 2 * kIntSize);
+ PrintF(out, "%6u %9u %10u\n", ast_id, pc_offset, loop_depth);
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
}
-
PrintF(out, "\n");
}
#ifdef OBJECT_PRINT
@@ -11354,7 +11347,6 @@ bool DependentCode::Contains(DependencyGroup group, Code* code) {
void DependentCode::DeoptimizeDependentCodeGroup(
Isolate* isolate,
DependentCode::DependencyGroup group) {
- ASSERT(AllowCodeDependencyChange::IsAllowed());
DisallowHeapAllocation no_allocation_scope;
DependentCode::GroupStartIndexes starts(this);
int start = starts.at(group);
@@ -15972,15 +15964,4 @@ void PropertyCell::AddDependentCode(Handle<Code> code) {
}
-const char* GetBailoutReason(BailoutReason reason) {
- ASSERT(reason < kLastErrorMessage);
-#define ERROR_MESSAGES_TEXTS(C, T) T,
- static const char* error_messages_[] = {
- ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
- };
-#undef ERROR_MESSAGES_TEXTS
- return error_messages_[reason];
-}
-
-
} } // namespace v8::internal
diff --git a/chromium/v8/src/objects.h b/chromium/v8/src/objects.h
index f800c5d580e..d370c32a1a4 100644
--- a/chromium/v8/src/objects.h
+++ b/chromium/v8/src/objects.h
@@ -333,7 +333,6 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
V(CONS_STRING_TYPE) \
V(CONS_ASCII_STRING_TYPE) \
V(SLICED_STRING_TYPE) \
- V(SLICED_ASCII_STRING_TYPE) \
V(EXTERNAL_STRING_TYPE) \
V(EXTERNAL_ASCII_STRING_TYPE) \
V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
@@ -417,8 +416,6 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
V(JS_TYPED_ARRAY_TYPE) \
V(JS_DATA_VIEW_TYPE) \
V(JS_PROXY_TYPE) \
- V(JS_SET_TYPE) \
- V(JS_MAP_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_WEAK_SET_TYPE) \
V(JS_REGEXP_TYPE) \
@@ -786,6 +783,7 @@ enum InstanceType {
// Pseudo-types
FIRST_TYPE = 0x0,
LAST_TYPE = JS_FUNCTION_TYPE,
+ INVALID_TYPE = FIRST_TYPE - 1,
FIRST_NAME_TYPE = FIRST_TYPE,
LAST_NAME_TYPE = SYMBOL_TYPE,
FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
@@ -1048,287 +1046,7 @@ class MaybeObject BASE_EMBEDDED {
V(AccessCheckNeeded) \
V(Cell) \
V(PropertyCell) \
- V(ObjectHashTable)
-
-
-#define ERROR_MESSAGES_LIST(V) \
- V(kNoReason, "no reason") \
- \
- V(k32BitValueInRegisterIsNotZeroExtended, \
- "32 bit value in register is not zero-extended") \
- V(kAlignmentMarkerExpected, "alignment marker expected") \
- V(kAllocationIsNotDoubleAligned, "Allocation is not double aligned") \
- V(kAPICallReturnedInvalidObject, "API call returned invalid object") \
- V(kArgumentsObjectValueInATestContext, \
- "arguments object value in a test context") \
- V(kArrayBoilerplateCreationFailed, "array boilerplate creation failed") \
- V(kArrayIndexConstantValueTooBig, "array index constant value too big") \
- V(kAssignmentToArguments, "assignment to arguments") \
- V(kAssignmentToLetVariableBeforeInitialization, \
- "assignment to let variable before initialization") \
- V(kAssignmentToLOOKUPVariable, "assignment to LOOKUP variable") \
- V(kAssignmentToParameterFunctionUsesArgumentsObject, \
- "assignment to parameter, function uses arguments object") \
- V(kAssignmentToParameterInArgumentsObject, \
- "assignment to parameter in arguments object") \
- V(kAttemptToUseUndefinedCache, "Attempt to use undefined cache") \
- V(kBadValueContextForArgumentsObjectValue, \
- "bad value context for arguments object value") \
- V(kBadValueContextForArgumentsValue, \
- "bad value context for arguments value") \
- V(kBailedOutDueToDependencyChange, "bailed out due to dependency change") \
- V(kBailoutWasNotPrepared, "bailout was not prepared") \
- V(kBinaryStubGenerateFloatingPointCode, \
- "BinaryStub_GenerateFloatingPointCode") \
- V(kBothRegistersWereSmisInSelectNonSmi, \
- "Both registers were smis in SelectNonSmi") \
- V(kCallToAJavaScriptRuntimeFunction, \
- "call to a JavaScript runtime function") \
- V(kCannotTranslatePositionInChangedArea, \
- "Cannot translate position in changed area") \
- V(kCodeGenerationFailed, "code generation failed") \
- V(kCodeObjectNotProperlyPatched, "code object not properly patched") \
- V(kCompoundAssignmentToLookupSlot, "compound assignment to lookup slot") \
- V(kContextAllocatedArguments, "context-allocated arguments") \
- V(kDebuggerIsActive, "debugger is active") \
- V(kDebuggerStatement, "DebuggerStatement") \
- V(kDeclarationInCatchContext, "Declaration in catch context") \
- V(kDeclarationInWithContext, "Declaration in with context") \
- V(kDefaultNaNModeNotSet, "Default NaN mode not set") \
- V(kDeleteWithGlobalVariable, "delete with global variable") \
- V(kDeleteWithNonGlobalVariable, "delete with non-global variable") \
- V(kDestinationOfCopyNotAligned, "Destination of copy not aligned") \
- V(kDontDeleteCellsCannotContainTheHole, \
- "DontDelete cells can't contain the hole") \
- V(kDoPushArgumentNotImplementedForDoubleType, \
- "DoPushArgument not implemented for double type") \
- V(kEmitLoadRegisterUnsupportedDoubleImmediate, \
- "EmitLoadRegister: Unsupported double immediate") \
- V(kEval, "eval") \
- V(kExpected0AsASmiSentinel, "Expected 0 as a Smi sentinel") \
- V(kExpectedAlignmentMarker, "expected alignment marker") \
- V(kExpectedPropertyCellInRegisterA2, \
- "Expected property cell in register a2") \
- V(kExpectedPropertyCellInRegisterEbx, \
- "Expected property cell in register ebx") \
- V(kExpectedPropertyCellInRegisterRbx, \
- "Expected property cell in register rbx") \
- V(kExpectingAlignmentForCopyBytes, \
- "Expecting alignment for CopyBytes") \
- V(kExternalStringExpectedButNotFound, \
- "external string expected, but not found") \
- V(kFailedBailedOutLastTime, "failed/bailed out last time") \
- V(kForInStatementIsNotFastCase, "ForInStatement is not fast case") \
- V(kForInStatementOptimizationIsDisabled, \
- "ForInStatement optimization is disabled") \
- V(kForInStatementWithNonLocalEachVariable, \
- "ForInStatement with non-local each variable") \
- V(kForOfStatement, "ForOfStatement") \
- V(kFrameIsExpectedToBeAligned, "frame is expected to be aligned") \
- V(kFunctionCallsEval, "function calls eval") \
- V(kFunctionIsAGenerator, "function is a generator") \
- V(kFunctionWithIllegalRedeclaration, "function with illegal redeclaration") \
- V(kGeneratedCodeIsTooLarge, "Generated code is too large") \
- V(kGeneratorFailedToResume, "Generator failed to resume") \
- V(kGenerator, "generator") \
- V(kGlobalFunctionsMustHaveInitialMap, \
- "Global functions must have initial map") \
- V(kHeapNumberMapRegisterClobbered, "HeapNumberMap register clobbered") \
- V(kImproperObjectOnPrototypeChainForStore, \
- "improper object on prototype chain for store") \
- V(kIndexIsNegative, "Index is negative") \
- V(kIndexIsTooLarge, "Index is too large") \
- V(kInlinedRuntimeFunctionClassOf, "inlined runtime function: ClassOf") \
- V(kInlinedRuntimeFunctionFastAsciiArrayJoin, \
- "inlined runtime function: FastAsciiArrayJoin") \
- V(kInlinedRuntimeFunctionGeneratorNext, \
- "inlined runtime function: GeneratorNext") \
- V(kInlinedRuntimeFunctionGeneratorThrow, \
- "inlined runtime function: GeneratorThrow") \
- V(kInlinedRuntimeFunctionGetFromCache, \
- "inlined runtime function: GetFromCache") \
- V(kInlinedRuntimeFunctionIsNonNegativeSmi, \
- "inlined runtime function: IsNonNegativeSmi") \
- V(kInlinedRuntimeFunctionIsRegExpEquivalent, \
- "inlined runtime function: IsRegExpEquivalent") \
- V(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf, \
- "inlined runtime function: IsStringWrapperSafeForDefaultValueOf") \
- V(kInliningBailedOut, "inlining bailed out") \
- V(kInputGPRIsExpectedToHaveUpper32Cleared, \
- "input GPR is expected to have upper32 cleared") \
- V(kInstanceofStubUnexpectedCallSiteCacheCheck, \
- "InstanceofStub unexpected call site cache (check)") \
- V(kInstanceofStubUnexpectedCallSiteCacheCmp1, \
- "InstanceofStub unexpected call site cache (cmp 1)") \
- V(kInstanceofStubUnexpectedCallSiteCacheCmp2, \
- "InstanceofStub unexpected call site cache (cmp 2)") \
- V(kInstanceofStubUnexpectedCallSiteCacheMov, \
- "InstanceofStub unexpected call site cache (mov)") \
- V(kInteger32ToSmiFieldWritingToNonSmiLocation, \
- "Integer32ToSmiField writing to non-smi location") \
- V(kInvalidCaptureReferenced, "Invalid capture referenced") \
- V(kInvalidElementsKindForInternalArrayOrInternalPackedArray, \
- "Invalid ElementsKind for InternalArray or InternalPackedArray") \
- V(kInvalidHandleScopeLevel, "Invalid HandleScope level") \
- V(kInvalidLeftHandSideInAssignment, "invalid left-hand side in assignment") \
- V(kInvalidLhsInCompoundAssignment, "invalid lhs in compound assignment") \
- V(kInvalidLhsInCountOperation, "invalid lhs in count operation") \
- V(kInvalidMinLength, "Invalid min_length") \
- V(kJSGlobalObjectNativeContextShouldBeANativeContext, \
- "JSGlobalObject::native_context should be a native context") \
- V(kJSGlobalProxyContextShouldNotBeNull, \
- "JSGlobalProxy::context() should not be null") \
- V(kJSObjectWithFastElementsMapHasSlowElements, \
- "JSObject with fast elements map has slow elements") \
- V(kLetBindingReInitialization, "Let binding re-initialization") \
- V(kLiveBytesCountOverflowChunkSize, "Live Bytes Count overflow chunk size") \
- V(kLiveEditFrameDroppingIsNotSupportedOnArm, \
- "LiveEdit frame dropping is not supported on arm") \
- V(kLiveEditFrameDroppingIsNotSupportedOnMips, \
- "LiveEdit frame dropping is not supported on mips") \
- V(kLiveEdit, "LiveEdit") \
- V(kLookupVariableInCountOperation, \
- "lookup variable in count operation") \
- V(kMapIsNoLongerInEax, "Map is no longer in eax") \
- V(kNoCasesLeft, "no cases left") \
- V(kNoEmptyArraysHereInEmitFastAsciiArrayJoin, \
- "No empty arrays here in EmitFastAsciiArrayJoin") \
- V(kNonInitializerAssignmentToConst, \
- "non-initializer assignment to const") \
- V(kNonSmiIndex, "Non-smi index") \
- V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \
- V(kNonSmiValue, "Non-smi value") \
- V(kNotEnoughVirtualRegistersForValues, \
- "not enough virtual registers for values") \
- V(kNotEnoughVirtualRegistersRegalloc, \
- "not enough virtual registers (regalloc)") \
- V(kObjectFoundInSmiOnlyArray, "object found in smi-only array") \
- V(kObjectLiteralWithComplexProperty, \
- "Object literal with complex property") \
- V(kOddballInStringTableIsNotUndefinedOrTheHole, \
- "oddball in string table is not undefined or the hole") \
- V(kOperandIsASmiAndNotAName, "Operand is a smi and not a name") \
- V(kOperandIsASmiAndNotAString, "Operand is a smi and not a string") \
- V(kOperandIsASmi, "Operand is a smi") \
- V(kOperandIsNotAName, "Operand is not a name") \
- V(kOperandIsNotANumber, "Operand is not a number") \
- V(kOperandIsNotASmi, "Operand is not a smi") \
- V(kOperandIsNotAString, "Operand is not a string") \
- V(kOperandIsNotSmi, "Operand is not smi") \
- V(kOperandNotANumber, "Operand not a number") \
- V(kOptimizedTooManyTimes, "optimized too many times") \
- V(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister, \
- "Out of virtual registers while trying to allocate temp register") \
- V(kParseScopeError, "parse/scope error") \
- V(kPossibleDirectCallToEval, "possible direct call to eval") \
- V(kPropertyAllocationCountFailed, "Property allocation count failed") \
- V(kReceivedInvalidReturnAddress, "Received invalid return address") \
- V(kReferenceToAVariableWhichRequiresDynamicLookup, \
- "reference to a variable which requires dynamic lookup") \
- V(kReferenceToGlobalLexicalVariable, \
- "reference to global lexical variable") \
- V(kReferenceToUninitializedVariable, "reference to uninitialized variable") \
- V(kRegisterDidNotMatchExpectedRoot, "Register did not match expected root") \
- V(kRegisterWasClobbered, "register was clobbered") \
- V(kScopedBlock, "ScopedBlock") \
- V(kSharedFunctionInfoLiteral, "SharedFunctionInfoLiteral") \
- V(kSmiAdditionOverflow, "Smi addition overflow") \
- V(kSmiSubtractionOverflow, "Smi subtraction overflow") \
- V(kStackFrameTypesMustMatch, "stack frame types must match") \
- V(kSwitchStatementMixedOrNonLiteralSwitchLabels, \
- "SwitchStatement: mixed or non-literal switch labels") \
- V(kSwitchStatementTooManyClauses, "SwitchStatement: too many clauses") \
- V(kTheInstructionShouldBeALui, "The instruction should be a lui") \
- V(kTheInstructionShouldBeAnOri, "The instruction should be an ori") \
- V(kTheInstructionToPatchShouldBeALoadFromPc, \
- "The instruction to patch should be a load from pc") \
- V(kTheInstructionToPatchShouldBeALui, \
- "The instruction to patch should be a lui") \
- V(kTheInstructionToPatchShouldBeAnOri, \
- "The instruction to patch should be an ori") \
- V(kTooManyParametersLocals, "too many parameters/locals") \
- V(kTooManyParameters, "too many parameters") \
- V(kTooManySpillSlotsNeededForOSR, "Too many spill slots needed for OSR") \
- V(kToOperandIsDoubleRegisterUnimplemented, \
- "ToOperand IsDoubleRegister unimplemented") \
- V(kToOperandUnsupportedDoubleImmediate, \
- "ToOperand Unsupported double immediate") \
- V(kTryCatchStatement, "TryCatchStatement") \
- V(kTryFinallyStatement, "TryFinallyStatement") \
- V(kUnableToEncodeValueAsSmi, "Unable to encode value as smi") \
- V(kUnalignedAllocationInNewSpace, "Unaligned allocation in new space") \
- V(kUndefinedValueNotLoaded, "Undefined value not loaded") \
- V(kUndoAllocationOfNonAllocatedMemory, \
- "Undo allocation of non allocated memory") \
- V(kUnexpectedAllocationTop, "Unexpected allocation top") \
- V(kUnexpectedElementsKindInArrayConstructor, \
- "Unexpected ElementsKind in array constructor") \
- V(kUnexpectedFallthroughFromCharCodeAtSlowCase, \
- "Unexpected fallthrough from CharCodeAt slow case") \
- V(kUnexpectedFallthroughFromCharFromCodeSlowCase, \
- "Unexpected fallthrough from CharFromCode slow case") \
- V(kUnexpectedFallThroughFromStringComparison, \
- "Unexpected fall-through from string comparison") \
- V(kUnexpectedFallThroughInBinaryStubGenerateFloatingPointCode, \
- "Unexpected fall-through in BinaryStub_GenerateFloatingPointCode") \
- V(kUnexpectedFallthroughToCharCodeAtSlowCase, \
- "Unexpected fallthrough to CharCodeAt slow case") \
- V(kUnexpectedFallthroughToCharFromCodeSlowCase, \
- "Unexpected fallthrough to CharFromCode slow case") \
- V(kUnexpectedFPUStackDepthAfterInstruction, \
- "Unexpected FPU stack depth after instruction") \
- V(kUnexpectedInitialMapForArrayFunction1, \
- "Unexpected initial map for Array function (1)") \
- V(kUnexpectedInitialMapForArrayFunction2, \
- "Unexpected initial map for Array function (2)") \
- V(kUnexpectedInitialMapForArrayFunction, \
- "Unexpected initial map for Array function") \
- V(kUnexpectedInitialMapForInternalArrayFunction, \
- "Unexpected initial map for InternalArray function") \
- V(kUnexpectedLevelAfterReturnFromApiCall, \
- "Unexpected level after return from api call") \
- V(kUnexpectedNumberOfPreAllocatedPropertyFields, \
- "Unexpected number of pre-allocated property fields") \
- V(kUnexpectedStringFunction, "Unexpected String function") \
- V(kUnexpectedStringType, "Unexpected string type") \
- V(kUnexpectedStringWrapperInstanceSize, \
- "Unexpected string wrapper instance size") \
- V(kUnexpectedTypeForRegExpDataFixedArrayExpected, \
- "Unexpected type for RegExp data, FixedArray expected") \
- V(kUnexpectedUnusedPropertiesOfStringWrapper, \
- "Unexpected unused properties of string wrapper") \
- V(kUninitializedKSmiConstantRegister, "Uninitialized kSmiConstantRegister") \
- V(kUnknown, "unknown") \
- V(kUnsupportedConstCompoundAssignment, \
- "unsupported const compound assignment") \
- V(kUnsupportedCountOperationWithConst, \
- "unsupported count operation with const") \
- V(kUnsupportedDoubleImmediate, "unsupported double immediate") \
- V(kUnsupportedLetCompoundAssignment, "unsupported let compound assignment") \
- V(kUnsupportedLookupSlotInDeclaration, \
- "unsupported lookup slot in declaration") \
- V(kUnsupportedNonPrimitiveCompare, "Unsupported non-primitive compare") \
- V(kUnsupportedPhiUseOfArguments, "Unsupported phi use of arguments") \
- V(kUnsupportedPhiUseOfConstVariable, \
- "Unsupported phi use of const variable") \
- V(kUnsupportedTaggedImmediate, "unsupported tagged immediate") \
- V(kVariableResolvedToWithContext, "Variable resolved to with context") \
- V(kWeShouldNotHaveAnEmptyLexicalContext, \
- "we should not have an empty lexical context") \
- V(kWithStatement, "WithStatement") \
- V(kWrongAddressOrValuePassedToRecordWrite, \
- "Wrong address or value passed to RecordWrite")
-
-
-#define ERROR_MESSAGES_CONSTANTS(C, T) C,
-enum BailoutReason {
- ERROR_MESSAGES_LIST(ERROR_MESSAGES_CONSTANTS)
- kLastErrorMessage
-};
-#undef ERROR_MESSAGES_CONSTANTS
-
-
-const char* GetBailoutReason(BailoutReason reason);
+ V(ObjectHashTable) \
// Object is the abstract superclass for all classes in the
@@ -4783,6 +4501,7 @@ class Code: public HeapObject {
V(KEYED_CALL_IC) \
V(STORE_IC) \
V(KEYED_STORE_IC) \
+ V(UNARY_OP_IC) \
V(BINARY_OP_IC) \
V(COMPARE_IC) \
V(COMPARE_NIL_IC) \
@@ -4901,7 +4620,8 @@ class Code: public HeapObject {
// TODO(danno): This is a bit of a hack right now since there are still
// clients of this API that pass "extra" values in for argc. These clients
// should be retrofitted to used ExtendedExtraICState.
- return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC;
+ return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC ||
+ kind == UNARY_OP_IC;
}
inline StubType type(); // Only valid for monomorphic IC stubs.
@@ -4916,6 +4636,7 @@ class Code: public HeapObject {
inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
inline bool is_call_stub() { return kind() == CALL_IC; }
inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
+ inline bool is_unary_op_stub() { return kind() == UNARY_OP_IC; }
inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
inline bool is_compare_nil_ic_stub() { return kind() == COMPARE_NIL_IC; }
@@ -4989,6 +4710,10 @@ class Code: public HeapObject {
inline CheckType check_type();
inline void set_check_type(CheckType value);
+ // [type-recording unary op type]: For kind UNARY_OP_IC.
+ inline byte unary_op_type();
+ inline void set_unary_op_type(byte value);
+
// [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
inline byte to_boolean_state();
@@ -5227,6 +4952,9 @@ class Code: public HeapObject {
// KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
static const int kStackSlotsFirstBit = 0;
static const int kStackSlotsBitCount = 24;
+ static const int kUnaryOpTypeFirstBit =
+ kStackSlotsFirstBit + kStackSlotsBitCount;
+ static const int kUnaryOpTypeBitCount = 3;
static const int kHasFunctionCacheFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kHasFunctionCacheBitCount = 1;
@@ -5235,12 +4963,15 @@ class Code: public HeapObject {
static const int kMarkedForDeoptimizationBitCount = 1;
STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
+ STATIC_ASSERT(kUnaryOpTypeFirstBit + kUnaryOpTypeBitCount <= 32);
STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <= 32);
STATIC_ASSERT(kMarkedForDeoptimizationFirstBit +
kMarkedForDeoptimizationBitCount <= 32);
class StackSlotsField: public BitField<int,
kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT
+ class UnaryOpTypeField: public BitField<int,
+ kUnaryOpTypeFirstBit, kUnaryOpTypeBitCount> {}; // NOLINT
class HasFunctionCacheField: public BitField<bool,
kHasFunctionCacheFirstBit, kHasFunctionCacheBitCount> {}; // NOLINT
class MarkedForDeoptimizationField: public BitField<bool,
@@ -5445,8 +5176,8 @@ class Map: public HeapObject {
inline void set_bit_field2(byte value);
// Bit field 3.
- inline uint32_t bit_field3();
- inline void set_bit_field3(uint32_t bits);
+ inline int bit_field3();
+ inline void set_bit_field3(int value);
class EnumLengthBits: public BitField<int, 0, 11> {};
class NumberOfOwnDescriptorsBits: public BitField<int, 11, 11> {};
@@ -5458,7 +5189,6 @@ class Map: public HeapObject {
class Deprecated: public BitField<bool, 27, 1> {};
class IsFrozen: public BitField<bool, 28, 1> {};
class IsUnstable: public BitField<bool, 29, 1> {};
- class IsMigrationTarget: public BitField<bool, 30, 1> {};
// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
@@ -5765,8 +5495,6 @@ class Map: public HeapObject {
inline bool is_frozen();
inline void mark_unstable();
inline bool is_stable();
- inline void set_migration_target(bool value);
- inline bool is_migration_target();
inline void deprecate();
inline bool is_deprecated();
inline bool CanBeDeprecated();
@@ -5913,6 +5641,7 @@ class Map: public HeapObject {
// the descriptor array.
inline void NotifyLeafMapLayoutChange();
+ inline bool CanOmitPrototypeChecks();
inline bool CanOmitMapChecks();
void AddDependentCompilationInfo(DependentCode::DependencyGroup group,
@@ -5929,7 +5658,7 @@ class Map: public HeapObject {
#ifdef VERIFY_HEAP
void SharedMapVerify();
- void VerifyOmittedMapChecks();
+ void VerifyOmittedPrototypeChecks();
#endif
inline int visitor_id();
@@ -6576,7 +6305,7 @@ class SharedFunctionInfo: public HeapObject {
// Disable (further) attempted optimization of all functions sharing this
// shared function info.
- void DisableOptimization(BailoutReason reason);
+ void DisableOptimization(const char* reason);
// Lookup the bailout ID and ASSERT that it exists in the non-optimized
// code, returns whether it asserted (i.e., always true if assertions are
@@ -10058,7 +9787,6 @@ class BreakPointInfo: public Struct {
V(kHandleScope, "handlescope", "(Handle scope)") \
V(kBuiltins, "builtins", "(Builtins)") \
V(kGlobalHandles, "globalhandles", "(Global handles)") \
- V(kEternalHandles, "eternalhandles", "(Eternal handles)") \
V(kThreadManager, "threadmanager", "(Thread manager)") \
V(kExtensions, "Extensions", "(Extensions)")
diff --git a/chromium/v8/src/optimizing-compiler-thread.cc b/chromium/v8/src/optimizing-compiler-thread.cc
index 337ddd4b2d2..21ef2371071 100644
--- a/chromium/v8/src/optimizing-compiler-thread.cc
+++ b/chromium/v8/src/optimizing-compiler-thread.cc
@@ -60,25 +60,12 @@ void OptimizingCompilerThread::Run() {
OS::Sleep(FLAG_parallel_recompilation_delay);
}
- switch (static_cast<StopFlag>(Acquire_Load(&stop_thread_))) {
- case CONTINUE:
- break;
- case STOP:
- if (FLAG_trace_parallel_recompilation) {
- time_spent_total_ = OS::Ticks() - epoch;
- }
- stop_semaphore_->Signal();
- return;
- case FLUSH:
- // The main thread is blocked, waiting for the stop semaphore.
- { AllowHandleDereference allow_handle_dereference;
- FlushInputQueue(true);
- }
- Release_Store(&queue_length_, static_cast<AtomicWord>(0));
- Release_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));
- stop_semaphore_->Signal();
- // Return to start of consumer loop.
- continue;
+ if (Acquire_Load(&stop_thread_)) {
+ stop_semaphore_->Signal();
+ if (FLAG_trace_parallel_recompilation) {
+ time_spent_total_ = OS::Ticks() - epoch;
+ }
+ return;
}
int64_t compiling_start = 0;
@@ -95,9 +82,7 @@ void OptimizingCompilerThread::Run() {
void OptimizingCompilerThread::CompileNext() {
OptimizingCompiler* optimizing_compiler = NULL;
- bool result = input_queue_.Dequeue(&optimizing_compiler);
- USE(result);
- ASSERT(result);
+ input_queue_.Dequeue(&optimizing_compiler);
Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1));
// The function may have already been optimized by OSR. Simply continue.
@@ -117,61 +102,26 @@ void OptimizingCompilerThread::CompileNext() {
}
-void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) {
- OptimizingCompiler* optimizing_compiler;
- // The optimizing compiler is allocated in the CompilationInfo's zone.
- while (input_queue_.Dequeue(&optimizing_compiler)) {
- // This should not block, since we have one signal on the input queue
- // semaphore corresponding to each element in the input queue.
- input_queue_semaphore_->Wait();
- CompilationInfo* info = optimizing_compiler->info();
- if (restore_function_code) {
- Handle<JSFunction> function = info->closure();
- function->ReplaceCode(function->shared()->code());
- }
- delete info;
- }
-}
-
-
-void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) {
- OptimizingCompiler* optimizing_compiler;
- // The optimizing compiler is allocated in the CompilationInfo's zone.
- while (output_queue_.Dequeue(&optimizing_compiler)) {
- CompilationInfo* info = optimizing_compiler->info();
- if (restore_function_code) {
- Handle<JSFunction> function = info->closure();
- function->ReplaceCode(function->shared()->code());
- }
- delete info;
- }
-}
-
-
-void OptimizingCompilerThread::Flush() {
- ASSERT(!IsOptimizerThread());
- Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH));
- input_queue_semaphore_->Signal();
- stop_semaphore_->Wait();
- FlushOutputQueue(true);
-}
-
-
void OptimizingCompilerThread::Stop() {
ASSERT(!IsOptimizerThread());
- Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP));
+ Release_Store(&stop_thread_, static_cast<AtomicWord>(true));
input_queue_semaphore_->Signal();
stop_semaphore_->Wait();
if (FLAG_parallel_recompilation_delay != 0) {
// Barrier when loading queue length is not necessary since the write
// happens in CompileNext on the same thread.
- // This is used only for testing.
while (NoBarrier_Load(&queue_length_) > 0) CompileNext();
InstallOptimizedFunctions();
} else {
- FlushInputQueue(false);
- FlushOutputQueue(false);
+ OptimizingCompiler* optimizing_compiler;
+ // The optimizing compiler is allocated in the CompilationInfo's zone.
+ while (input_queue_.Dequeue(&optimizing_compiler)) {
+ delete optimizing_compiler->info();
+ }
+ while (output_queue_.Dequeue(&optimizing_compiler)) {
+ delete optimizing_compiler->info();
+ }
}
if (FLAG_trace_parallel_recompilation) {
diff --git a/chromium/v8/src/optimizing-compiler-thread.h b/chromium/v8/src/optimizing-compiler-thread.h
index cbd4d0e4872..275ceb40b71 100644
--- a/chromium/v8/src/optimizing-compiler-thread.h
+++ b/chromium/v8/src/optimizing-compiler-thread.h
@@ -54,13 +54,13 @@ class OptimizingCompilerThread : public Thread {
install_mutex_(OS::CreateMutex()),
time_spent_compiling_(0),
time_spent_total_(0) {
- NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));
+ NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(false));
NoBarrier_Store(&queue_length_, static_cast<AtomicWord>(0));
}
void Run();
void Stop();
- void Flush();
+ void CompileNext();
void QueueForOptimization(OptimizingCompiler* optimizing_compiler);
void InstallOptimizedFunctions();
@@ -92,13 +92,6 @@ class OptimizingCompilerThread : public Thread {
}
private:
- enum StopFlag { CONTINUE, STOP, FLUSH };
-
- void FlushInputQueue(bool restore_function_code);
- void FlushOutputQueue(bool restore_function_code);
-
- void CompileNext();
-
#ifdef DEBUG
int thread_id_;
Mutex* thread_id_mutex_;
diff --git a/chromium/v8/src/parser.cc b/chromium/v8/src/parser.cc
index 4947790395f..df568ef1bbb 100644
--- a/chromium/v8/src/parser.cc
+++ b/chromium/v8/src/parser.cc
@@ -3197,20 +3197,6 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
factory()->NewNumberLiteral(1),
position);
}
- // The same idea for '-foo' => 'foo*(-1)'.
- if (op == Token::SUB) {
- return factory()->NewBinaryOperation(Token::MUL,
- expression,
- factory()->NewNumberLiteral(-1),
- position);
- }
- // ...and one more time for '~foo' => 'foo^(~0)'.
- if (op == Token::BIT_NOT) {
- return factory()->NewBinaryOperation(Token::BIT_XOR,
- expression,
- factory()->NewNumberLiteral(~0),
- position);
- }
return factory()->NewUnaryOperation(op, expression, position);
diff --git a/chromium/v8/src/platform-linux.cc b/chromium/v8/src/platform-linux.cc
index 885683398e2..5c252bbf884 100644
--- a/chromium/v8/src/platform-linux.cc
+++ b/chromium/v8/src/platform-linux.cc
@@ -239,8 +239,7 @@ bool OS::ArmUsingHardFloat() {
#else
#if defined(__ARM_PCS_VFP)
return true;
-#elif defined(__ARM_PCS) || defined(__SOFTFP__) || defined(__SOFTFP) || \
- !defined(__VFP_FP__)
+#elif defined(__ARM_PCS) || defined(__SOFTFP) || !defined(__VFP_FP__)
return false;
#else
#error "Your version of GCC does not report the FP ABI compiled for." \
diff --git a/chromium/v8/src/profile-generator-inl.h b/chromium/v8/src/profile-generator-inl.h
index 6791c88c56e..d92085ac32d 100644
--- a/chromium/v8/src/profile-generator-inl.h
+++ b/chromium/v8/src/profile-generator-inl.h
@@ -92,8 +92,6 @@ CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
case OTHER:
case EXTERNAL:
return program_entry_;
- case IDLE:
- return idle_entry_;
default: return NULL;
}
}
diff --git a/chromium/v8/src/profile-generator.cc b/chromium/v8/src/profile-generator.cc
index 86bd17b70a0..e772a546471 100644
--- a/chromium/v8/src/profile-generator.cc
+++ b/chromium/v8/src/profile-generator.cc
@@ -220,7 +220,7 @@ double ProfileNode::GetTotalMillis() const {
void ProfileNode::Print(int indent) {
- OS::Print("%5u %5u %*c %s%s %d #%d",
+ OS::Print("%5u %5u %*c %s%s #%d %d",
total_ticks_, self_ticks_,
indent, ' ',
entry_->name_prefix(),
@@ -614,8 +614,6 @@ const char* const ProfileGenerator::kAnonymousFunctionName =
"(anonymous function)";
const char* const ProfileGenerator::kProgramEntryName =
"(program)";
-const char* const ProfileGenerator::kIdleEntryName =
- "(idle)";
const char* const ProfileGenerator::kGarbageCollectorEntryName =
"(garbage collector)";
const char* const ProfileGenerator::kUnresolvedFunctionName =
@@ -626,8 +624,6 @@ ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
: profiles_(profiles),
program_entry_(
profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
- idle_entry_(
- profiles->NewCodeEntry(Logger::FUNCTION_TAG, kIdleEntryName)),
gc_entry_(
profiles->NewCodeEntry(Logger::BUILTIN_TAG,
kGarbageCollectorEntryName)),
diff --git a/chromium/v8/src/profile-generator.h b/chromium/v8/src/profile-generator.h
index 99aeb1f5c7f..0cc397ed9bf 100644
--- a/chromium/v8/src/profile-generator.h
+++ b/chromium/v8/src/profile-generator.h
@@ -342,7 +342,6 @@ class ProfileGenerator {
static const char* const kAnonymousFunctionName;
static const char* const kProgramEntryName;
- static const char* const kIdleEntryName;
static const char* const kGarbageCollectorEntryName;
// Used to represent frames for which we have no reliable way to
// detect function.
@@ -354,7 +353,6 @@ class ProfileGenerator {
CpuProfilesCollection* profiles_;
CodeMap code_map_;
CodeEntry* program_entry_;
- CodeEntry* idle_entry_;
CodeEntry* gc_entry_;
CodeEntry* unresolved_entry_;
diff --git a/chromium/v8/src/runtime.cc b/chromium/v8/src/runtime.cc
index 10de6f9e5ec..ef6eeb3a497 100644
--- a/chromium/v8/src/runtime.cc
+++ b/chromium/v8/src/runtime.cc
@@ -66,30 +66,6 @@
#include "v8threads.h"
#include "vm-state-inl.h"
-#ifdef V8_I18N_SUPPORT
-#include "i18n.h"
-#include "unicode/brkiter.h"
-#include "unicode/calendar.h"
-#include "unicode/coll.h"
-#include "unicode/curramt.h"
-#include "unicode/datefmt.h"
-#include "unicode/dcfmtsym.h"
-#include "unicode/decimfmt.h"
-#include "unicode/dtfmtsym.h"
-#include "unicode/dtptngen.h"
-#include "unicode/locid.h"
-#include "unicode/numfmt.h"
-#include "unicode/numsys.h"
-#include "unicode/smpdtfmt.h"
-#include "unicode/timezone.h"
-#include "unicode/uchar.h"
-#include "unicode/ucol.h"
-#include "unicode/ucurr.h"
-#include "unicode/uloc.h"
-#include "unicode/unum.h"
-#include "unicode/uversion.h"
-#endif
-
#ifndef _STLP_VENDOR_CSTD
// STLPort doesn't import fpclassify and isless into the std namespace.
using std::fpclassify;
@@ -3020,7 +2996,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
JavaScriptFrame* frame = stack_iterator.frame();
ASSERT_EQ(frame->function(), generator_object->function());
- ASSERT(frame->function()->is_compiled());
STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
@@ -7261,6 +7236,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
+ SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
+
+ CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+ return isolate->heap()->NumberFromInt32(~x);
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -8495,7 +8479,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
}
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (FLAG_parallel_recompilation && sync_with_compiler_thread) {
- while (function->IsInRecompileQueue() ||
+ while (function->IsMarkedForParallelRecompilation() ||
+ function->IsInRecompileQueue() ||
function->IsMarkedForInstallingRecompiledCode()) {
isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
OS::Sleep(50);
@@ -8562,21 +8547,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
// Use linear search of the unoptimized code's back edge table to find
// the AST id matching the PC.
- uint32_t target_pc_offset =
- static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
+ Address start = unoptimized->instruction_start();
+ unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
+ Address table_cursor = start + unoptimized->back_edge_table_offset();
+ uint32_t table_length = Memory::uint32_at(table_cursor);
+ table_cursor += kIntSize;
uint32_t loop_depth = 0;
-
- for (FullCodeGenerator::BackEdgeTableIterator back_edges(*unoptimized);
- !back_edges.Done();
- back_edges.Next()) {
- if (back_edges.pc_offset() == target_pc_offset) {
- ast_id = back_edges.ast_id();
- loop_depth = back_edges.loop_depth();
+ for (unsigned i = 0; i < table_length; ++i) {
+ // Table entries are (AST id, pc offset) pairs.
+ uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
+ if (pc_offset == target_pc_offset) {
+ ast_id = BailoutId(static_cast<int>(Memory::uint32_at(table_cursor)));
+ loop_depth = Memory::uint32_at(table_cursor + 2 * kIntSize);
break;
}
+ table_cursor += FullCodeGenerator::kBackEdgeEntrySize;
}
ASSERT(!ast_id.IsNone());
-
if (FLAG_trace_osr) {
PrintF("[replacing on-stack at AST id %d, loop depth %d in ",
ast_id.ToInt(), loop_depth);
@@ -8693,8 +8680,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
CONVERT_SMI_ARG_CHECKED(offset, 3);
CONVERT_SMI_ARG_CHECKED(argc, 4);
- RUNTIME_ASSERT(offset >= 0);
- RUNTIME_ASSERT(argc >= 0);
+ ASSERT(offset >= 0);
+ ASSERT(argc >= 0);
// If there are too many arguments, allocate argv via malloc.
const int argv_small_size = 10;
@@ -9487,7 +9474,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
ASSERT_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
- source = Handle<String>(FlattenGetString(source));
+ source = Handle<String>(source->TryFlattenGetString());
// Optimized fast case where we only have ASCII characters.
Handle<Object> result;
if (source->IsSeqOneByteString()) {
@@ -11227,7 +11214,6 @@ static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
? frame_inspector->GetParameter(i)
: isolate->heap()->undefined_value(),
isolate);
- ASSERT(!value->IsTheHole());
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
@@ -11242,15 +11228,12 @@ static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
// Second fill all stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
- Handle<Object> value(frame_inspector->GetExpression(i), isolate);
- if (value->IsTheHole()) continue;
-
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
SetProperty(isolate,
target,
Handle<String>(scope_info->StackLocalName(i)),
- value,
+ Handle<Object>(frame_inspector->GetExpression(i), isolate),
NONE,
kNonStrictMode),
Handle<JSObject>());
@@ -11277,7 +11260,6 @@ static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
// Parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) {
- ASSERT(!frame->GetParameter(i)->IsTheHole());
HandleScope scope(isolate);
Handle<Object> value = GetProperty(
isolate, target, Handle<String>(scope_info->ParameterName(i)));
@@ -11286,7 +11268,6 @@ static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
// Stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
- if (frame->GetExpression(i)->IsTheHole()) continue;
HandleScope scope(isolate);
Handle<Object> value = GetProperty(
isolate, target, Handle<String>(scope_info->StackLocalName(i)));
@@ -12021,15 +12002,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
JavaScriptFrameIterator frame_it(isolate, id);
JavaScriptFrame* frame = frame_it.frame();
- Handle<JSFunction> fun =
- Handle<JSFunction>(frame->function());
Handle<SharedFunctionInfo> shared =
- Handle<SharedFunctionInfo>(fun->shared());
-
- if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
- return isolate->heap()->undefined_value();
- }
-
+ Handle<SharedFunctionInfo>(frame->function()->shared());
Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
int len = 0;
@@ -12042,14 +12016,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
int current_statement_pos = break_location_iterator.statement_position();
while (!break_location_iterator.Done()) {
- if (break_location_iterator.pc() > frame->pc()) {
- if (break_location_iterator.IsStepInLocation(isolate)) {
- Smi* position_value = Smi::FromInt(break_location_iterator.position());
- JSObject::SetElement(array, len,
- Handle<Object>(position_value, isolate),
- NONE, kNonStrictMode);
- len++;
- }
+ if (break_location_iterator.IsStepInLocation(isolate)) {
+ Smi* position_value = Smi::FromInt(break_location_iterator.position());
+ JSObject::SetElement(array, len,
+ Handle<Object>(position_value, isolate),
+ NONE, kNonStrictMode);
+ len++;
}
// Advance iterator.
break_location_iterator.Next();
@@ -13392,489 +13364,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
#endif // ENABLE_DEBUGGER_SUPPORT
-#ifdef V8_I18N_SUPPORT
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
-
- v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
-
- // Return value which denotes invalid language tag.
- const char* const kInvalidTag = "invalid-tag";
-
- UErrorCode error = U_ZERO_ERROR;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
-
- uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &error);
- if (U_FAILURE(error) || icu_length == 0) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
- }
-
- char result[ULOC_FULLNAME_CAPACITY];
-
- // Force strict BCP47 rules.
- uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
-
- if (U_FAILURE(error)) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
- }
-
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
-
- const icu::Locale* available_locales = NULL;
- int32_t count = 0;
-
- if (service->IsUtf8EqualTo(CStrVector("collator"))) {
- available_locales = icu::Collator::getAvailableLocales(count);
- } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
- available_locales = icu::NumberFormat::getAvailableLocales(count);
- } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
- available_locales = icu::DateFormat::getAvailableLocales(count);
- } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
- available_locales = icu::BreakIterator::getAvailableLocales(count);
- }
-
- UErrorCode error = U_ZERO_ERROR;
- char result[ULOC_FULLNAME_CAPACITY];
- Handle<JSObject> locales =
- isolate->factory()->NewJSObject(isolate->object_function());
-
- for (int32_t i = 0; i < count; ++i) {
- const char* icu_name = available_locales[i].getName();
-
- error = U_ZERO_ERROR;
- // No need to force strict BCP47 rules.
- uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
- if (U_FAILURE(error)) {
- // This shouldn't happen, but lets not break the user.
- continue;
- }
-
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- locales,
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
- isolate->factory()->NewNumber(i),
- NONE));
- }
-
- return *locales;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
- SealHandleScope shs(isolate);
-
- ASSERT(args.length() == 0);
-
- icu::Locale default_locale;
-
- // Set the locale
- char result[ULOC_FULLNAME_CAPACITY];
- UErrorCode status = U_ZERO_ERROR;
- uloc_toLanguageTag(
- default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
- if (U_SUCCESS(status)) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
- }
-
- return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 1);
-
- CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
-
- uint32_t length = static_cast<uint32_t>(input->length()->Number());
- Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
- Handle<Name> maximized =
- isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
- Handle<Name> base =
- isolate->factory()->NewStringFromAscii(CStrVector("base"));
- for (unsigned int i = 0; i < length; ++i) {
- MaybeObject* maybe_string = input->GetElement(i);
- Object* locale_id;
- if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
-
- v8::String::Utf8Value utf8_locale_id(
- v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
-
- UErrorCode error = U_ZERO_ERROR;
-
- // Convert from BCP47 to ICU format.
- // de-DE-u-co-phonebk -> de_DE@collation=phonebook
- char icu_locale[ULOC_FULLNAME_CAPACITY];
- int icu_locale_length = 0;
- uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
- &icu_locale_length, &error);
- if (U_FAILURE(error) || icu_locale_length == 0) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
-
- // Maximize the locale.
- // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
- char icu_max_locale[ULOC_FULLNAME_CAPACITY];
- uloc_addLikelySubtags(
- icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
-
- // Remove extensions from maximized locale.
- // de_Latn_DE@collation=phonebook -> de_Latn_DE
- char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
- uloc_getBaseName(
- icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
-
- // Get original name without extensions.
- // de_DE@collation=phonebook -> de_DE
- char icu_base_locale[ULOC_FULLNAME_CAPACITY];
- uloc_getBaseName(
- icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
-
- // Convert from ICU locale format to BCP47 format.
- // de_Latn_DE -> de-Latn-DE
- char base_max_locale[ULOC_FULLNAME_CAPACITY];
- uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
- ULOC_FULLNAME_CAPACITY, FALSE, &error);
-
- // de_DE -> de-DE
- char base_locale[ULOC_FULLNAME_CAPACITY];
- uloc_toLanguageTag(
- icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
-
- if (U_FAILURE(error)) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
-
- Handle<JSObject> result =
- isolate->factory()->NewJSObject(isolate->object_function());
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- result,
- maximized,
- isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
- NONE));
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- result,
- base,
- isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
- NONE));
- output->set(i, *result);
- }
-
- Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
- result->set_length(Smi::FromInt(length));
- return *result;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 3);
-
- CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
-
- Handle<ObjectTemplateInfo> date_format_template =
- I18N::GetTemplate(isolate);
-
- // Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- date_format_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
-
- // Set date time formatter as internal field of the resulting JS object.
- icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
- isolate, locale, options, resolved);
-
- if (!date_format) return isolate->ThrowIllegalOperation();
-
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
-
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
- NONE));
-
- Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
- v8::Utils::ToLocal(local_object));
- // Make object handle weak so we can delete the data format once GC kicks in.
- wrapper.MakeWeak<void>(NULL, &DateFormat::DeleteDateFormat);
- wrapper.ClearAndLeak();
- return *local_object;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 2);
-
- CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
-
- bool has_pending_exception = false;
- double millis = Execution::ToNumber(date, &has_pending_exception)->Number();
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
-
- icu::SimpleDateFormat* date_format =
- DateFormat::UnpackDateFormat(isolate, date_format_holder);
- if (!date_format) return isolate->ThrowIllegalOperation();
-
- icu::UnicodeString result;
- date_format->format(millis, result);
-
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 2);
-
- CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
-
- v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
- icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
- icu::SimpleDateFormat* date_format =
- DateFormat::UnpackDateFormat(isolate, date_format_holder);
- if (!date_format) return isolate->ThrowIllegalOperation();
-
- UErrorCode status = U_ZERO_ERROR;
- UDate date = date_format->parse(u_date, status);
- if (U_FAILURE(status)) return isolate->heap()->undefined_value();
-
- bool has_pending_exception = false;
- Handle<JSDate> result = Handle<JSDate>::cast(
- Execution::NewDate(static_cast<double>(date), &has_pending_exception));
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
- return *result;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 3);
-
- CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
-
- Handle<ObjectTemplateInfo> number_format_template =
- I18N::GetTemplate(isolate);
-
- // Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- number_format_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
-
- // Set number formatter as internal field of the resulting JS object.
- icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
- isolate, locale, options, resolved);
-
- if (!number_format) return isolate->ThrowIllegalOperation();
-
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
-
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
- NONE));
-
- Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
- v8::Utils::ToLocal(local_object));
- // Make object handle weak so we can delete the number format once GC kicks
- // in.
- wrapper.MakeWeak<void>(NULL, &NumberFormat::DeleteNumberFormat);
- wrapper.ClearAndLeak();
- return *local_object;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 2);
-
- CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
-
- bool has_pending_exception = false;
- double value = Execution::ToNumber(number, &has_pending_exception)->Number();
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
-
- icu::DecimalFormat* number_format =
- NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
- if (!number_format) return isolate->ThrowIllegalOperation();
-
- icu::UnicodeString result;
- number_format->format(value, result);
-
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 2);
-
- CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
-
- v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
- icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
- icu::DecimalFormat* number_format =
- NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
- if (!number_format) return isolate->ThrowIllegalOperation();
-
- UErrorCode status = U_ZERO_ERROR;
- icu::Formattable result;
- // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
- // to be part of Chrome.
- // TODO(cira): Include currency parsing code using parseCurrency call.
- // We need to check if the formatter parses all currencies or only the
- // one it was constructed with (it will impact the API - how to return ISO
- // code and the value).
- number_format->parse(u_number, result, status);
- if (U_FAILURE(status)) return isolate->heap()->undefined_value();
-
- switch (result.getType()) {
- case icu::Formattable::kDouble:
- return *isolate->factory()->NewNumber(result.getDouble());
- case icu::Formattable::kLong:
- return *isolate->factory()->NewNumberFromInt(result.getLong());
- case icu::Formattable::kInt64:
- return *isolate->factory()->NewNumber(
- static_cast<double>(result.getInt64()));
- default:
- return isolate->heap()->undefined_value();
- }
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 3);
-
- CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
-
- Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
-
- // Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- collator_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
-
- // Set collator as internal field of the resulting JS object.
- icu::Collator* collator = Collator::InitializeCollator(
- isolate, locale, options, resolved);
-
- if (!collator) return isolate->ThrowIllegalOperation();
-
- local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
-
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
- local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("collator")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
- NONE));
-
- Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
- v8::Utils::ToLocal(local_object));
- // Make object handle weak so we can delete the collator once GC kicks in.
- wrapper.MakeWeak<void>(NULL, &Collator::DeleteCollator);
- wrapper.ClearAndLeak();
- return *local_object;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
- HandleScope scope(isolate);
-
- ASSERT(args.length() == 3);
-
- CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
- CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
-
- icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
- if (!collator) return isolate->ThrowIllegalOperation();
-
- v8::String::Value string_value1(v8::Utils::ToLocal(string1));
- v8::String::Value string_value2(v8::Utils::ToLocal(string2));
- const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
- const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
- UErrorCode status = U_ZERO_ERROR;
- UCollationResult result = collator->compare(u_string1,
- string_value1.length(),
- u_string2,
- string_value2.length(),
- status);
- if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
-
- return *isolate->factory()->NewNumberFromInt(result);
-}
-#endif // V8_I18N_SUPPORT
-
-
// Finds the script object from the script data. NOTE: This operation uses
// heap traversal to find the function generated for the source position
// for the requested break point. For lazily compiled functions several heap
@@ -13993,18 +13482,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
- if (!object->IsJSObject()) return Smi::FromInt(0);
- Handle<JSObject> js_object = Handle<JSObject>::cast(object);
- if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
- JSObject::MigrateInstance(js_object);
- return *object;
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
SealHandleScope shs(isolate);
// This is only called from codegen, so checks might be more lax.
@@ -14248,9 +13725,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
ASSERT(proto->IsJSGlobalObject());
obj = JSReceiver::cast(proto);
}
- if (obj->IsJSProxy())
- return isolate->heap()->undefined_value();
-
ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
JSObject::cast(obj)->HasFastElements()));
ASSERT(obj->IsJSObject());
diff --git a/chromium/v8/src/runtime.h b/chromium/v8/src/runtime.h
index 23e91f2ae9e..398cb3bcc24 100644
--- a/chromium/v8/src/runtime.h
+++ b/chromium/v8/src/runtime.h
@@ -109,7 +109,6 @@ namespace internal {
F(DebugCallbackSupportsStepping, 1, 1) \
F(DebugPrepareStepInIfStepping, 1, 1) \
F(FlattenString, 1, 1) \
- F(MigrateInstance, 1, 1) \
\
/* Array join support */ \
F(PushIfAbsent, 2, 1) \
@@ -158,6 +157,7 @@ namespace internal {
F(NumberOr, 2, 1) \
F(NumberAnd, 2, 1) \
F(NumberXor, 2, 1) \
+ F(NumberNot, 1, 1) \
\
F(NumberShl, 2, 1) \
F(NumberShr, 2, 1) \
@@ -534,35 +534,6 @@ namespace internal {
#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
#endif
-
-#ifdef V8_I18N_SUPPORT
-#define RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F) \
- /* i18n support */ \
- /* Standalone, helper methods. */ \
- F(CanonicalizeLanguageTag, 1, 1) \
- F(AvailableLocalesOf, 1, 1) \
- F(GetDefaultICULocale, 0, 1) \
- F(GetLanguageTagVariants, 1, 1) \
- \
- /* Date format and parse. */ \
- F(CreateDateTimeFormat, 3, 1) \
- F(InternalDateFormat, 2, 1) \
- F(InternalDateParse, 2, 1) \
- \
- /* Number format and parse. */ \
- F(CreateNumberFormat, 3, 1) \
- F(InternalNumberFormat, 2, 1) \
- F(InternalNumberParse, 2, 1) \
- \
- /* Collator. */ \
- F(CreateCollator, 3, 1) \
- F(InternalCompare, 3, 1) \
-
-#else
-#define RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
-#endif
-
-
#ifdef DEBUG
#define RUNTIME_FUNCTION_LIST_DEBUG(F) \
/* Testing */ \
@@ -580,8 +551,7 @@ namespace internal {
RUNTIME_FUNCTION_LIST_ALWAYS_1(F) \
RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
RUNTIME_FUNCTION_LIST_DEBUG(F) \
- RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F) \
- RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
+ RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
// ----------------------------------------------------------------------------
// INLINE_FUNCTION_LIST defines all inlined functions accessed
diff --git a/chromium/v8/src/runtime.js b/chromium/v8/src/runtime.js
index 5339570ef6e..90fb36b4223 100644
--- a/chromium/v8/src/runtime.js
+++ b/chromium/v8/src/runtime.js
@@ -294,6 +294,20 @@ function BIT_XOR(y) {
}
+// ECMA-262, section 11.4.7, page 47.
+function UNARY_MINUS() {
+ var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+ return %NumberUnaryMinus(x);
+}
+
+
+// ECMA-262, section 11.4.8, page 48.
+function BIT_NOT() {
+ var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+ return %NumberNot(x);
+}
+
+
// ECMA-262, section 11.7.1, page 51.
function SHL(y) {
var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
diff --git a/chromium/v8/src/sampler.cc b/chromium/v8/src/sampler.cc
index 1d0cdedd1fc..d72ed1acdb8 100644
--- a/chromium/v8/src/sampler.cc
+++ b/chromium/v8/src/sampler.cc
@@ -38,10 +38,7 @@
#include <signal.h>
#include <sys/time.h>
#include <sys/syscall.h>
-// OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
-// and is a typedef for struct sigcontext. There is no uc_mcontext.
-#if (!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
- && !defined(__OpenBSD__)
+#if !defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)
#include <ucontext.h>
#endif
#include <unistd.h>
@@ -333,9 +330,7 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
#else
// Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
-#if !defined(__OpenBSD__)
mcontext_t& mcontext = ucontext->uc_mcontext;
-#endif
#if defined(__linux__) || defined(__ANDROID__)
#if V8_HOST_ARCH_IA32
state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
@@ -389,6 +384,7 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
#endif // V8_HOST_ARCH_*
#elif defined(__OpenBSD__)
+ USE(mcontext);
#if V8_HOST_ARCH_IA32
state.pc = reinterpret_cast<Address>(ucontext->sc_eip);
state.sp = reinterpret_cast<Address>(ucontext->sc_esp);
@@ -619,7 +615,8 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate,
// Avoid collecting traces while doing GC.
if (state == GC) return;
- Address js_entry_sp = isolate->js_entry_sp();
+ const Address js_entry_sp =
+ Isolate::js_entry_sp(isolate->thread_local_top());
if (js_entry_sp == 0) {
// Not executing JS now.
return;
diff --git a/chromium/v8/src/serialize.cc b/chromium/v8/src/serialize.cc
index 746c926653d..6c5a620a418 100644
--- a/chromium/v8/src/serialize.cc
+++ b/chromium/v8/src/serialize.cc
@@ -1304,7 +1304,6 @@ void StartupSerializer::SerializeStrongReferences() {
// No active or weak handles.
CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
- CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
// We don't support serializing installed extensions.
CHECK(!isolate->has_installed_extensions());
diff --git a/chromium/v8/src/spaces.h b/chromium/v8/src/spaces.h
index aa864b66ba5..b47452e421f 100644
--- a/chromium/v8/src/spaces.h
+++ b/chromium/v8/src/spaces.h
@@ -784,9 +784,8 @@ class Page : public MemoryChunk {
// Maximum object size that fits in a page. Objects larger than that size
// are allocated in large object space and are never moved in memory. This
// also applies to new space allocation, since objects are never migrated
- // from new space to large object space. Takes double alignment into account.
- static const int kMaxNonCodeHeapObjectSize =
- kNonCodeObjectAreaSize - kPointerSize;
+ // from new space to large object space.
+ static const int kMaxNonCodeHeapObjectSize = kNonCodeObjectAreaSize;
// Page size mask.
static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
diff --git a/chromium/v8/src/splay-tree-inl.h b/chromium/v8/src/splay-tree-inl.h
index 42024756e9b..4eca71d1004 100644
--- a/chromium/v8/src/splay-tree-inl.h
+++ b/chromium/v8/src/splay-tree-inl.h
@@ -91,12 +91,6 @@ bool SplayTree<Config, Allocator>::FindInternal(const Key& key) {
template<typename Config, class Allocator>
-bool SplayTree<Config, Allocator>::Contains(const Key& key) {
- return FindInternal(key);
-}
-
-
-template<typename Config, class Allocator>
bool SplayTree<Config, Allocator>::Find(const Key& key, Locator* locator) {
if (FindInternal(key)) {
locator->bind(root_);
@@ -299,10 +293,9 @@ void SplayTree<Config, Allocator>::ForEach(Callback* callback) {
template <typename Config, class Allocator> template <class Callback>
void SplayTree<Config, Allocator>::ForEachNode(Callback* callback) {
- if (root_ == NULL) return;
// Pre-allocate some space for tiny trees.
List<Node*, Allocator> nodes_to_visit(10, allocator_);
- nodes_to_visit.Add(root_, allocator_);
+ if (root_ != NULL) nodes_to_visit.Add(root_, allocator_);
int pos = 0;
while (pos < nodes_to_visit.length()) {
Node* node = nodes_to_visit[pos++];
diff --git a/chromium/v8/src/splay-tree.h b/chromium/v8/src/splay-tree.h
index f393027a82c..8844d8a8ffe 100644
--- a/chromium/v8/src/splay-tree.h
+++ b/chromium/v8/src/splay-tree.h
@@ -39,9 +39,9 @@ namespace internal {
//
// typedef Key: the key type
// typedef Value: the value type
-// static const Key kNoKey: the dummy key used when no key is set
-// static Value kNoValue(): the dummy value used to initialize nodes
-// static int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function
+// static const kNoKey: the dummy key used when no key is set
+// static const kNoValue: the dummy value used to initialize nodes
+// int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function
//
// The tree is also parameterized by an allocation policy
// (Allocator). The policy is used for allocating lists in the C free
@@ -74,11 +74,6 @@ class SplayTree {
UNREACHABLE();
}
- AllocationPolicy allocator() { return allocator_; }
-
- // Checks if there is a mapping for the key.
- bool Contains(const Key& key);
-
// Inserts the given key in this tree with the given value. Returns
// true if a node was inserted, otherwise false. If found the locator
// is enabled and provides access to the mapping for the key.
@@ -109,9 +104,6 @@ class SplayTree {
// Remove the node with the given key from the tree.
bool Remove(const Key& key);
- // Remove all keys from the tree.
- void Clear() { ResetRoot(); }
-
bool is_empty() { return root_ == NULL; }
// Perform the splay operation for the given key. Moves the node with
diff --git a/chromium/v8/src/type-info.cc b/chromium/v8/src/type-info.cc
index 336b459d6b7..769df07e4fa 100644
--- a/chromium/v8/src/type-info.cc
+++ b/chromium/v8/src/type-info.cc
@@ -384,6 +384,17 @@ void TypeFeedbackOracle::CompareType(TypeFeedbackId id,
}
+Handle<Type> TypeFeedbackOracle::UnaryType(TypeFeedbackId id) {
+ Handle<Object> object = GetInfo(id);
+ if (!object->IsCode()) {
+ return handle(Type::None(), isolate());
+ }
+ Handle<Code> code = Handle<Code>::cast(object);
+ ASSERT(code->is_unary_op_stub());
+ return UnaryOpStub(code->extended_extra_ic_state()).GetType(isolate());
+}
+
+
void TypeFeedbackOracle::BinaryType(TypeFeedbackId id,
Handle<Type>* left,
Handle<Type>* right,
@@ -647,6 +658,7 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
}
break;
+ case Code::UNARY_OP_IC:
case Code::BINARY_OP_IC:
case Code::COMPARE_IC:
case Code::TO_BOOLEAN_IC:
diff --git a/chromium/v8/src/type-info.h b/chromium/v8/src/type-info.h
index 4b376c84bdc..1a7c67dfb88 100644
--- a/chromium/v8/src/type-info.h
+++ b/chromium/v8/src/type-info.h
@@ -297,6 +297,7 @@ class TypeFeedbackOracle: public ZoneObject {
byte ToBooleanTypes(TypeFeedbackId id);
// Get type information for arithmetic operations and compares.
+ Handle<Type> UnaryType(TypeFeedbackId id);
void BinaryType(TypeFeedbackId id,
Handle<Type>* left,
Handle<Type>* right,
diff --git a/chromium/v8/src/types.h b/chromium/v8/src/types.h
index fc69c785295..b2eb60c6920 100644
--- a/chromium/v8/src/types.h
+++ b/chromium/v8/src/types.h
@@ -303,11 +303,6 @@ struct Bounds {
explicit Bounds(Handle<Type> t) : lower(t), upper(t) {}
Bounds(Type* t, Isolate* isl) : lower(t, isl), upper(t, isl) {}
- // Unrestricted bounds.
- static Bounds Unbounded(Isolate* isl) {
- return Bounds(Type::None(), Type::Any(), isl);
- }
-
// Meet: both b1 and b2 are known to hold.
static Bounds Both(Bounds b1, Bounds b2, Isolate* isl) {
return Bounds(
diff --git a/chromium/v8/src/typing.cc b/chromium/v8/src/typing.cc
index f8e2a7c206d..4220d2110db 100644
--- a/chromium/v8/src/typing.cc
+++ b/chromium/v8/src/typing.cc
@@ -40,8 +40,7 @@ AstTyper::AstTyper(CompilationInfo* info)
Handle<Code>(info->closure()->shared()->code()),
Handle<Context>(info->closure()->context()->native_context()),
info->isolate(),
- info->zone()),
- store_(info->zone()) {
+ info->zone()) {
InitializeAstVisitor();
}
@@ -80,16 +79,12 @@ void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
for (int i = 0; i < stmts->length(); ++i) {
Statement* stmt = stmts->at(i);
RECURSE(Visit(stmt));
- if (stmt->IsJump()) break;
}
}
void AstTyper::VisitBlock(Block* stmt) {
RECURSE(VisitStatements(stmt->statements()));
- if (stmt->labels() != NULL) {
- store_.Forget(); // Control may transfer here via 'break l'.
- }
}
@@ -103,41 +98,30 @@ void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
void AstTyper::VisitIfStatement(IfStatement* stmt) {
- // Collect type feedback.
+ RECURSE(Visit(stmt->condition()));
+ RECURSE(Visit(stmt->then_statement()));
+ RECURSE(Visit(stmt->else_statement()));
+
if (!stmt->condition()->ToBooleanIsTrue() &&
!stmt->condition()->ToBooleanIsFalse()) {
stmt->condition()->RecordToBooleanTypeFeedback(oracle());
}
-
- RECURSE(Visit(stmt->condition()));
- Effects then_effects = EnterEffects();
- RECURSE(Visit(stmt->then_statement()));
- ExitEffects();
- Effects else_effects = EnterEffects();
- RECURSE(Visit(stmt->else_statement()));
- ExitEffects();
- then_effects.Alt(else_effects);
- store_.Seq(then_effects);
}
void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
- // TODO(rossberg): is it worth having a non-termination effect?
}
void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
- // TODO(rossberg): is it worth having a non-termination effect?
}
void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
- // Collect type feedback.
+ RECURSE(Visit(stmt->expression()));
+
// TODO(rossberg): we only need this for inlining into test contexts...
stmt->expression()->RecordToBooleanTypeFeedback(oracle());
-
- RECURSE(Visit(stmt->expression()));
- // TODO(rossberg): is it worth having a non-termination effect?
}
@@ -149,18 +133,14 @@ void AstTyper::VisitWithStatement(WithStatement* stmt) {
void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
RECURSE(Visit(stmt->tag()));
-
ZoneList<CaseClause*>* clauses = stmt->cases();
SwitchStatement::SwitchType switch_type = stmt->switch_type();
- Effects local_effects(zone());
- bool complex_effects = false; // True for label effects or fall-through.
-
for (int i = 0; i < clauses->length(); ++i) {
CaseClause* clause = clauses->at(i);
- Effects clause_effects = EnterEffects();
-
if (!clause->is_default()) {
Expression* label = clause->label();
+ RECURSE(Visit(label));
+
SwitchStatement::SwitchType label_switch_type =
label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH :
label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH :
@@ -169,32 +149,13 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
switch_type = label_switch_type;
else if (switch_type != label_switch_type)
switch_type = SwitchStatement::GENERIC_SWITCH;
-
- RECURSE(Visit(label));
- if (!clause_effects.IsEmpty()) complex_effects = true;
- }
-
- ZoneList<Statement*>* stmts = clause->statements();
- RECURSE(VisitStatements(stmts));
- ExitEffects();
- if (stmts->is_empty() || stmts->last()->IsJump()) {
- local_effects.Alt(clause_effects);
- } else {
- complex_effects = true;
}
+ RECURSE(VisitStatements(clause->statements()));
}
-
- if (complex_effects) {
- store_.Forget(); // Reached this in unknown state.
- } else {
- store_.Seq(local_effects);
- }
-
if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
switch_type = SwitchStatement::GENERIC_SWITCH;
stmt->set_switch_type(switch_type);
- // Collect type feedback.
// TODO(rossberg): can we eliminate this special case and extra loop?
if (switch_type == SwitchStatement::SMI_SWITCH) {
for (int i = 0; i < clauses->length(); ++i) {
@@ -207,31 +168,22 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
- // Collect type feedback.
+ RECURSE(Visit(stmt->body()));
+ RECURSE(Visit(stmt->cond()));
+
if (!stmt->cond()->ToBooleanIsTrue()) {
stmt->cond()->RecordToBooleanTypeFeedback(oracle());
}
-
- // TODO(rossberg): refine the unconditional Forget (here and elsewhere) by
- // computing the set of variables assigned in only some of the origins of the
- // control transfer (such as the loop body here).
- store_.Forget(); // Control may transfer here via looping or 'continue'.
- RECURSE(Visit(stmt->body()));
- RECURSE(Visit(stmt->cond()));
- store_.Forget(); // Control may transfer here via 'break'.
}
void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
- // Collect type feedback.
+ RECURSE(Visit(stmt->cond()));
+ RECURSE(Visit(stmt->body()));
+
if (!stmt->cond()->ToBooleanIsTrue()) {
stmt->cond()->RecordToBooleanTypeFeedback(oracle());
}
-
- store_.Forget(); // Control may transfer here via looping or 'continue'.
- RECURSE(Visit(stmt->cond()));
- RECURSE(Visit(stmt->body()));
- store_.Forget(); // Control may transfer here via termination or 'break'.
}
@@ -239,65 +191,45 @@ void AstTyper::VisitForStatement(ForStatement* stmt) {
if (stmt->init() != NULL) {
RECURSE(Visit(stmt->init()));
}
- store_.Forget(); // Control may transfer here via looping.
if (stmt->cond() != NULL) {
- // Collect type feedback.
- stmt->cond()->RecordToBooleanTypeFeedback(oracle());
-
RECURSE(Visit(stmt->cond()));
+
+ stmt->cond()->RecordToBooleanTypeFeedback(oracle());
}
RECURSE(Visit(stmt->body()));
- store_.Forget(); // Control may transfer here via 'continue'.
if (stmt->next() != NULL) {
RECURSE(Visit(stmt->next()));
}
- store_.Forget(); // Control may transfer here via termination or 'break'.
}
void AstTyper::VisitForInStatement(ForInStatement* stmt) {
- // Collect type feedback.
- stmt->RecordTypeFeedback(oracle());
-
RECURSE(Visit(stmt->enumerable()));
- store_.Forget(); // Control may transfer here via looping or 'continue'.
RECURSE(Visit(stmt->body()));
- store_.Forget(); // Control may transfer here via 'break'.
+
+ stmt->RecordTypeFeedback(oracle());
}
void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {
RECURSE(Visit(stmt->iterable()));
- store_.Forget(); // Control may transfer here via looping or 'continue'.
RECURSE(Visit(stmt->body()));
- store_.Forget(); // Control may transfer here via 'break'.
}
void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
- Effects try_effects = EnterEffects();
RECURSE(Visit(stmt->try_block()));
- ExitEffects();
- Effects catch_effects = EnterEffects();
- store_.Forget(); // Control may transfer here via 'throw'.
RECURSE(Visit(stmt->catch_block()));
- ExitEffects();
- try_effects.Alt(catch_effects);
- store_.Seq(try_effects);
- // At this point, only variables that were reassigned in the catch block are
- // still remembered.
}
void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
RECURSE(Visit(stmt->try_block()));
- store_.Forget(); // Control may transfer here via 'throw'.
RECURSE(Visit(stmt->finally_block()));
}
void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
- store_.Forget(); // May do whatever.
}
@@ -310,18 +242,11 @@ void AstTyper::VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral* expr) {
void AstTyper::VisitConditional(Conditional* expr) {
- // Collect type feedback.
- expr->condition()->RecordToBooleanTypeFeedback(oracle());
-
RECURSE(Visit(expr->condition()));
- Effects then_effects = EnterEffects();
RECURSE(Visit(expr->then_expression()));
- ExitEffects();
- Effects else_effects = EnterEffects();
RECURSE(Visit(expr->else_expression()));
- ExitEffects();
- then_effects.Alt(else_effects);
- store_.Seq(then_effects);
+
+ expr->condition()->RecordToBooleanTypeFeedback(oracle());
NarrowType(expr, Bounds::Either(
expr->then_expression()->bounds(),
@@ -330,10 +255,7 @@ void AstTyper::VisitConditional(Conditional* expr) {
void AstTyper::VisitVariableProxy(VariableProxy* expr) {
- Variable* var = expr->var();
- if (var->IsStackAllocated()) {
- NarrowType(expr, store_.LookupBounds(variable_index(var)));
- }
+ // TODO(rossberg): typing of variables
}
@@ -352,8 +274,8 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
for (int i = 0; i < properties->length(); ++i) {
ObjectLiteral::Property* prop = properties->at(i);
+ RECURSE(Visit(prop->value()));
- // Collect type feedback.
if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
!CompileTimeValue::IsCompileTimeValue(prop->value())) ||
prop->kind() == ObjectLiteral::Property::COMPUTED) {
@@ -361,8 +283,6 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
prop->RecordTypeFeedback(oracle());
}
}
-
- RECURSE(Visit(prop->value()));
}
NarrowType(expr, Bounds(Type::Object(), isolate_));
@@ -383,33 +303,29 @@ void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
void AstTyper::VisitAssignment(Assignment* expr) {
// TODO(rossberg): Can we clean this up?
if (expr->is_compound()) {
- // Collect type feedback.
+ RECURSE(Visit(expr->binary_operation()));
+
Expression* target = expr->target();
Property* prop = target->AsProperty();
if (prop != NULL) {
prop->RecordTypeFeedback(oracle(), zone());
- expr->RecordTypeFeedback(oracle(), zone());
+ if (!prop->key()->IsPropertyName()) { // i.e., keyed
+ expr->RecordTypeFeedback(oracle(), zone());
+ }
}
- RECURSE(Visit(expr->binary_operation()));
-
NarrowType(expr, expr->binary_operation()->bounds());
} else {
- // Collect type feedback.
- if (expr->target()->IsProperty()) {
- expr->RecordTypeFeedback(oracle(), zone());
- }
-
RECURSE(Visit(expr->target()));
RECURSE(Visit(expr->value()));
- NarrowType(expr, expr->value()->bounds());
- }
+ if (expr->target()->AsProperty()) {
+ expr->RecordTypeFeedback(oracle(), zone());
+ }
- VariableProxy* proxy = expr->target()->AsVariableProxy();
- if (proxy != NULL && proxy->var()->IsStackAllocated()) {
- store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
+ NarrowType(expr, expr->value()->bounds());
}
+ // TODO(rossberg): handle target variables
}
@@ -417,40 +333,28 @@ void AstTyper::VisitYield(Yield* expr) {
RECURSE(Visit(expr->generator_object()));
RECURSE(Visit(expr->expression()));
- // We don't know anything about the result type.
+ // We don't know anything about the type.
}
void AstTyper::VisitThrow(Throw* expr) {
RECURSE(Visit(expr->exception()));
- // TODO(rossberg): is it worth having a non-termination effect?
NarrowType(expr, Bounds(Type::None(), isolate_));
}
void AstTyper::VisitProperty(Property* expr) {
- // Collect type feedback.
- expr->RecordTypeFeedback(oracle(), zone());
-
RECURSE(Visit(expr->obj()));
RECURSE(Visit(expr->key()));
- // We don't know anything about the result type.
+ expr->RecordTypeFeedback(oracle(), zone());
+
+ // We don't know anything about the type.
}
void AstTyper::VisitCall(Call* expr) {
- // Collect type feedback.
- Expression* callee = expr->expression();
- Property* prop = callee->AsProperty();
- if (prop != NULL) {
- if (prop->key()->IsPropertyName())
- expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
- } else {
- expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
- }
-
RECURSE(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
@@ -458,19 +362,20 @@ void AstTyper::VisitCall(Call* expr) {
RECURSE(Visit(arg));
}
- VariableProxy* proxy = expr->expression()->AsVariableProxy();
- if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
- store_.Forget(); // Eval could do whatever to local variables.
+ Expression* callee = expr->expression();
+ Property* prop = callee->AsProperty();
+ if (prop != NULL) {
+ if (prop->key()->IsPropertyName())
+ expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
+ } else {
+ expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
}
- // We don't know anything about the result type.
+ // We don't know anything about the type.
}
void AstTyper::VisitCallNew(CallNew* expr) {
- // Collect type feedback.
- expr->RecordTypeFeedback(oracle());
-
RECURSE(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
@@ -478,7 +383,9 @@ void AstTyper::VisitCallNew(CallNew* expr) {
RECURSE(Visit(arg));
}
- // We don't know anything about the result type.
+ expr->RecordTypeFeedback(oracle());
+
+ // We don't know anything about the type.
}
@@ -489,19 +396,21 @@ void AstTyper::VisitCallRuntime(CallRuntime* expr) {
RECURSE(Visit(arg));
}
- // We don't know anything about the result type.
+ // We don't know anything about the type.
}
void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
+ RECURSE(Visit(expr->expression()));
+
// Collect type feedback.
+ Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId());
+ NarrowLowerType(expr->expression(), op_type);
if (expr->op() == Token::NOT) {
// TODO(rossberg): only do in test or value context.
expr->expression()->RecordToBooleanTypeFeedback(oracle());
}
- RECURSE(Visit(expr->expression()));
-
switch (expr->op()) {
case Token::NOT:
case Token::DELETE:
@@ -510,6 +419,16 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
case Token::VOID:
NarrowType(expr, Bounds(Type::Undefined(), isolate_));
break;
+ case Token::ADD:
+ case Token::SUB: {
+ Type* upper = *expr->expression()->bounds().upper;
+ if (!upper->Is(Type::Number())) upper = Type::Number();
+ NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
+ break;
+ }
+ case Token::BIT_NOT:
+ NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
+ break;
case Token::TYPEOF:
NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
break;
@@ -520,25 +439,22 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
void AstTyper::VisitCountOperation(CountOperation* expr) {
- // Collect type feedback.
+ RECURSE(Visit(expr->expression()));
+
expr->RecordTypeFeedback(oracle(), zone());
Property* prop = expr->expression()->AsProperty();
if (prop != NULL) {
prop->RecordTypeFeedback(oracle(), zone());
}
- RECURSE(Visit(expr->expression()));
-
NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
-
- VariableProxy* proxy = expr->expression()->AsVariableProxy();
- if (proxy != NULL && proxy->var()->IsStackAllocated()) {
- store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
- }
}
void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
+ RECURSE(Visit(expr->left()));
+ RECURSE(Visit(expr->right()));
+
// Collect type feedback.
Handle<Type> type, left_type, right_type;
Maybe<int> fixed_right_arg;
@@ -554,29 +470,15 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
NarrowType(expr, expr->right()->bounds());
break;
case Token::OR:
- case Token::AND: {
- Effects left_effects = EnterEffects();
- RECURSE(Visit(expr->left()));
- ExitEffects();
- Effects right_effects = EnterEffects();
- RECURSE(Visit(expr->right()));
- ExitEffects();
- left_effects.Alt(right_effects);
- store_.Seq(left_effects);
-
+ case Token::AND:
NarrowType(expr, Bounds::Either(
expr->left()->bounds(), expr->right()->bounds(), isolate_));
break;
- }
case Token::BIT_OR:
case Token::BIT_AND: {
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
Type* upper = Type::Union(
expr->left()->bounds().upper, expr->right()->bounds().upper);
if (!upper->Is(Type::Signed32())) upper = Type::Signed32();
@@ -586,18 +488,12 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::BIT_XOR:
case Token::SHL:
case Token::SAR:
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
break;
case Token::SHR:
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_));
break;
case Token::ADD: {
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
Bounds l = expr->left()->bounds();
Bounds r = expr->right()->bounds();
Type* lower =
@@ -617,8 +513,6 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::MUL:
case Token::DIV:
case Token::MOD:
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
break;
default:
@@ -628,6 +522,9 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
void AstTyper::VisitCompareOperation(CompareOperation* expr) {
+ RECURSE(Visit(expr->left()));
+ RECURSE(Visit(expr->right()));
+
// Collect type feedback.
Handle<Type> left_type, right_type, combined_type;
oracle()->CompareType(expr->CompareOperationFeedbackId(),
@@ -636,9 +533,6 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) {
NarrowLowerType(expr->right(), right_type);
expr->set_combined_type(combined_type);
- RECURSE(Visit(expr->left()));
- RECURSE(Visit(expr->right()));
-
NarrowType(expr, Bounds(Type::Boolean(), isolate_));
}
diff --git a/chromium/v8/src/typing.h b/chromium/v8/src/typing.h
index c942b006327..ceef9843650 100644
--- a/chromium/v8/src/typing.h
+++ b/chromium/v8/src/typing.h
@@ -35,7 +35,6 @@
#include "compiler.h"
#include "type-info.h"
#include "types.h"
-#include "effects.h"
#include "zone.h"
#include "scopes.h"
@@ -58,13 +57,8 @@ class AstTyper: public AstVisitor {
private:
explicit AstTyper(CompilationInfo* info);
- static const int kNoVar = INT_MIN;
- typedef v8::internal::Effects<int, kNoVar> Effects;
- typedef v8::internal::NestedEffects<int, kNoVar> Store;
-
CompilationInfo* info_;
TypeFeedbackOracle oracle_;
- Store store_;
TypeFeedbackOracle* oracle() { return &oracle_; }
Zone* zone() const { return info_->zone(); }
@@ -76,17 +70,6 @@ class AstTyper: public AstVisitor {
e->set_bounds(Bounds::NarrowLower(e->bounds(), t, isolate_));
}
- Effects EnterEffects() {
- store_ = store_.Push();
- return store_.Top();
- }
- void ExitEffects() { store_ = store_.Pop(); }
-
- int variable_index(Variable* var) {
- return var->IsStackLocal() ? var->index() :
- var->IsParameter() ? -var->index() : kNoVar;
- }
-
void VisitDeclarations(ZoneList<Declaration*>* declarations);
void VisitStatements(ZoneList<Statement*>* statements);
diff --git a/chromium/v8/src/v8.cc b/chromium/v8/src/v8.cc
index 93f3efb2e3f..521d064129a 100644
--- a/chromium/v8/src/v8.cc
+++ b/chromium/v8/src/v8.cc
@@ -272,10 +272,9 @@ void V8::InitializeOncePerProcessImpl() {
FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
}
- if (FLAG_parallel_recompilation &&
- (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs)) {
+ if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs) {
+ // Tracing hydrogen do not work with parallel recompilation.
FLAG_parallel_recompilation = false;
- PrintF("Parallel recompilation has been disabled for tracing.\n");
}
if (FLAG_sweeper_threads <= 0) {
diff --git a/chromium/v8/src/v8globals.h b/chromium/v8/src/v8globals.h
index 6ec75478875..c3f1f01f944 100644
--- a/chromium/v8/src/v8globals.h
+++ b/chromium/v8/src/v8globals.h
@@ -363,8 +363,7 @@ enum StateTag {
GC,
COMPILER,
OTHER,
- EXTERNAL,
- IDLE
+ EXTERNAL
};
diff --git a/chromium/v8/src/version.cc b/chromium/v8/src/version.cc
index 5142d389c21..292389aa4ab 100644
--- a/chromium/v8/src/version.cc
+++ b/chromium/v8/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 20
-#define BUILD_NUMBER 17
-#define PATCH_LEVEL 0
+#define BUILD_NUMBER 15
+#define PATCH_LEVEL 5
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/chromium/v8/src/x64/assembler-x64-inl.h b/chromium/v8/src/x64/assembler-x64-inl.h
index 826c06e5bad..ae9aeee8122 100644
--- a/chromium/v8/src/x64/assembler-x64-inl.h
+++ b/chromium/v8/src/x64/assembler-x64-inl.h
@@ -373,14 +373,13 @@ void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
bool RelocInfo::IsPatchedReturnSequence() {
// The recognized call sequence is:
- // movq(kScratchRegister, address); call(kScratchRegister);
+ // movq(kScratchRegister, immediate64); call(kScratchRegister);
// It only needs to be distinguished from a return sequence
// movq(rsp, rbp); pop(rbp); ret(n); int3 *6
// The 11th byte is int3 (0xCC) in the return sequence and
// REX.WB (0x48+register bit) for the call sequence.
#ifdef ENABLE_DEBUGGER_SUPPORT
- return pc_[Assembler::kMoveAddressIntoScratchRegisterInstructionLength] !=
- 0xCC;
+ return pc_[2 + kPointerSize] != 0xCC;
#else
return false;
#endif
diff --git a/chromium/v8/src/x64/assembler-x64.cc b/chromium/v8/src/x64/assembler-x64.cc
index 8969d89a6a7..f5939c3b7e1 100644
--- a/chromium/v8/src/x64/assembler-x64.cc
+++ b/chromium/v8/src/x64/assembler-x64.cc
@@ -164,7 +164,10 @@ void CpuFeatures::Probe() {
// Patch the code at the current PC with a call to the target address.
// Additional guard int3 instructions can be added if required.
void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
- int code_size = Assembler::kCallSequenceLength + guard_bytes;
+ // Load register with immediate 64 and call through a register instructions
+ // takes up 13 bytes and int3 takes up one byte.
+ static const int kCallCodeSize = 13;
+ int code_size = kCallCodeSize + guard_bytes;
// Create a code patcher.
CodePatcher patcher(pc_, code_size);
@@ -180,7 +183,7 @@ void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
patcher.masm()->call(r10);
// Check that the size of the code generated is as expected.
- ASSERT_EQ(Assembler::kCallSequenceLength,
+ ASSERT_EQ(kCallCodeSize,
patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
// Add the requested number of int3 instructions after the call.
diff --git a/chromium/v8/src/x64/assembler-x64.h b/chromium/v8/src/x64/assembler-x64.h
index 4e36b6e4bc4..07afc129dc8 100644
--- a/chromium/v8/src/x64/assembler-x64.h
+++ b/chromium/v8/src/x64/assembler-x64.h
@@ -579,36 +579,29 @@ class Assembler : public AssemblerBase {
// Distance between the address of the code target in the call instruction
// and the return address pushed on the stack.
static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
- // The length of call(kScratchRegister).
- static const int kCallScratchRegisterInstructionLength = 3;
- // The length of call(Immediate32).
- static const int kShortCallInstructionLength = 5;
- // The length of movq(kScratchRegister, address).
- static const int kMoveAddressIntoScratchRegisterInstructionLength =
- 2 + kPointerSize;
- // The length of movq(kScratchRegister, address) and call(kScratchRegister).
- static const int kCallSequenceLength =
- kMoveAddressIntoScratchRegisterInstructionLength +
- kCallScratchRegisterInstructionLength;
-
- // The js return and debug break slot must be able to contain an indirect
- // call sequence, some x64 JS code is padded with int3 to make it large
- // enough to hold an instruction when the debugger patches it.
- static const int kJSReturnSequenceLength = kCallSequenceLength;
- static const int kDebugBreakSlotLength = kCallSequenceLength;
- static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset;
- // Distance between the start of the JS return sequence and where the
- // 32-bit displacement of a short call would be. The short call is from
- // SetDebugBreakAtIC from debug-x64.cc.
- static const int kPatchReturnSequenceAddressOffset =
- kJSReturnSequenceLength - kPatchDebugBreakSlotReturnOffset;
// Distance between the start of the JS return sequence and where the
- // 32-bit displacement of a short call would be. The short call is from
- // SetDebugBreakAtIC from debug-x64.cc.
- static const int kPatchDebugBreakSlotAddressOffset =
- kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset;
- static const int kRealPatchReturnSequenceAddressOffset =
- kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
+ // 32-bit displacement of a near call would be, relative to the pushed
+ // return address. TODO: Use return sequence length instead.
+ // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
+ static const int kPatchReturnSequenceAddressOffset = 13 - 4;
+ // Distance between start of patched debug break slot and where the
+ // 32-bit displacement of a near call would be, relative to the pushed
+ // return address. TODO: Use return sequence length instead.
+ // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
+ static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
+ // TODO(X64): Rename this, removing the "Real", after changing the above.
+ static const int kRealPatchReturnSequenceAddressOffset = 2;
+
+ // Some x64 JS code is padded with int3 to make it large
+ // enough to hold an instruction when the debugger patches it.
+ static const int kJumpInstructionLength = 13;
+ static const int kCallInstructionLength = 13;
+ static const int kJSReturnSequenceLength = 13;
+ static const int kShortCallInstructionLength = 5;
+ static const int kPatchDebugBreakSlotReturnOffset = 4;
+
+ // The debug break slot must be able to contain a call instruction.
+ static const int kDebugBreakSlotLength = kCallInstructionLength;
// One byte opcode for test eax,0xXXXXXXXX.
static const byte kTestEaxByte = 0xA9;
diff --git a/chromium/v8/src/x64/builtins-x64.cc b/chromium/v8/src/x64/builtins-x64.cc
index 18a6e566c6c..d34e4f70d9a 100644
--- a/chromium/v8/src/x64/builtins-x64.cc
+++ b/chromium/v8/src/x64/builtins-x64.cc
@@ -59,9 +59,9 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
int num_extra_args = 0;
if (extra_args == NEEDS_CALLED_FUNCTION) {
num_extra_args = 1;
- __ PopReturnAddressTo(kScratchRegister);
+ __ pop(kScratchRegister); // Save return address.
__ push(rdi);
- __ PushReturnAddressFrom(kScratchRegister);
+ __ push(kScratchRegister); // Restore return address.
} else {
ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
}
@@ -249,7 +249,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (FLAG_debug_code) {
__ cmpq(rsi, rdi);
__ Assert(less_equal,
- kUnexpectedNumberOfPreAllocatedPropertyFields);
+ "Unexpected number of pre-allocated property fields.");
}
__ InitializeFieldsWithFiller(rcx, rsi, rdx);
__ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
@@ -280,7 +280,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ subq(rdx, rcx);
// Done if no extra properties are to be allocated.
__ j(zero, &allocated);
- __ Assert(positive, kPropertyAllocationCountFailed);
+ __ Assert(positive, "Property allocation count failed.");
// Scale the number of elements by pointer size and add the header for
// FixedArrays to the start of the next object calculation from above.
@@ -429,10 +429,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
}
// Remove caller arguments from the stack and return.
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
__ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->constructed_objects(), 1);
__ ret(0);
@@ -723,7 +723,7 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
__ ret(2 * kPointerSize); // Remove state, rax.
__ bind(&not_tos_rax);
- __ Abort(kNoCasesLeft);
+ __ Abort("no cases left");
}
@@ -772,9 +772,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
{ Label done;
__ testq(rax, rax);
__ j(not_zero, &done);
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ Push(masm->isolate()->factory()->undefined_value());
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx);
__ incq(rax);
__ bind(&done);
}
@@ -895,9 +895,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ cmpq(rdx, Immediate(1));
__ j(not_equal, &non_proxy);
- __ PopReturnAddressTo(rdx);
+ __ pop(rdx); // return address
__ push(rdi); // re-add proxy object as additional argument
- __ PushReturnAddressFrom(rdx);
+ __ push(rdx);
__ incq(rax);
__ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
__ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
@@ -1113,9 +1113,9 @@ void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
// Will both indicate a NULL and a Smi.
STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
- __ Check(not_smi, kUnexpectedInitialMapForInternalArrayFunction);
+ __ Check(not_smi, "Unexpected initial map for InternalArray function");
__ CmpObjectType(rbx, MAP_TYPE, rcx);
- __ Check(equal, kUnexpectedInitialMapForInternalArrayFunction);
+ __ Check(equal, "Unexpected initial map for InternalArray function");
}
// Run the native code for the InternalArray function called as a normal
@@ -1143,9 +1143,9 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
// Will both indicate a NULL and a Smi.
STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
- __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
+ __ Check(not_smi, "Unexpected initial map for Array function");
__ CmpObjectType(rbx, MAP_TYPE, rcx);
- __ Check(equal, kUnexpectedInitialMapForArrayFunction);
+ __ Check(equal, "Unexpected initial map for Array function");
}
// Run the native code for the Array function called as a normal function.
@@ -1173,7 +1173,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx);
__ cmpq(rdi, rcx);
- __ Assert(equal, kUnexpectedStringFunction);
+ __ Assert(equal, "Unexpected String function");
}
// Load the first argument into rax and get rid of the rest
@@ -1182,9 +1182,9 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
__ testq(rax, rax);
__ j(zero, &no_arguments);
__ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ lea(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
__ movq(rax, rbx);
// Lookup the argument in the number to string cache.
@@ -1219,9 +1219,9 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset),
Immediate(JSValue::kSize >> kPointerSizeLog2));
- __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
+ __ Assert(equal, "Unexpected string wrapper instance size");
__ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0));
- __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
+ __ Assert(equal, "Unexpected unused properties of string wrapper");
}
__ movq(FieldOperand(rax, HeapObject::kMapOffset), rcx);
@@ -1268,9 +1268,9 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// stack, and jump back to the case where the argument is a string.
__ bind(&no_arguments);
__ LoadRoot(rbx, Heap::kempty_stringRootIndex);
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ lea(rsp, Operand(rsp, kPointerSize));
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
__ jmp(&argument_is_string);
// At this point the argument is already a string. Call runtime to
@@ -1313,10 +1313,10 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
__ pop(rbp);
// Remove caller arguments from the stack.
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
__ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
}
diff --git a/chromium/v8/src/x64/code-stubs-x64.cc b/chromium/v8/src/x64/code-stubs-x64.cc
index ad33a8c6319..551a71690e7 100644
--- a/chromium/v8/src/x64/code-stubs-x64.cc
+++ b/chromium/v8/src/x64/code-stubs-x64.cc
@@ -246,6 +246,17 @@ void ToBooleanStub::InitializeInterfaceDescriptor(
}
+void UnaryOpStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { rax };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
void StoreGlobalStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
@@ -419,12 +430,12 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
// Create a new closure through the slower runtime call.
__ bind(&gc);
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx); // Temporarily remove return address.
__ pop(rdx);
__ push(rsi);
__ push(rdx);
__ PushRoot(Heap::kFalseValueRootIndex);
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx); // Restore return address.
__ TailCallRuntime(Runtime::kNewClosure, 3, 1);
}
@@ -500,8 +511,9 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
Label after_sentinel;
__ JumpIfNotSmi(rcx, &after_sentinel, Label::kNear);
if (FLAG_debug_code) {
+ const char* message = "Expected 0 as a Smi sentinel";
__ cmpq(rcx, Immediate(0));
- __ Assert(equal, kExpected0AsASmiSentinel);
+ __ Assert(equal, message);
}
__ movq(rcx, GlobalObjectOperand());
__ movq(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset));
@@ -683,13 +695,13 @@ void BinaryOpStub::Initialize() {}
void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx); // Save return address.
__ push(rdx);
__ push(rax);
// Left and right arguments are now on top.
__ Push(Smi::FromInt(MinorKey()));
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx); // Push return address.
// Patch the caller to an appropriate specialized stub and return the
// operation result to the caller of the stub.
@@ -942,7 +954,7 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm,
// Set the map.
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
- kHeapNumberMapRegisterClobbered);
+ "HeapNumberMap register clobbered.");
__ movq(FieldOperand(rax, HeapObject::kMapOffset),
heap_number_map);
__ cvtqsi2sd(xmm0, rbx);
@@ -962,7 +974,8 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm,
}
// No fall-through from this generated code.
if (FLAG_debug_code) {
- __ Abort(kUnexpectedFallThroughInBinaryStubGenerateFloatingPointCode);
+ __ Abort("Unexpected fall-through in "
+ "BinaryStub_GenerateFloatingPointCode.");
}
}
@@ -971,10 +984,10 @@ static void BinaryOpStub_GenerateRegisterArgsPushUnderReturn(
MacroAssembler* masm) {
// Push arguments, but ensure they are under the return address
// for a tail call.
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ push(rdx);
__ push(rax);
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
}
@@ -2142,10 +2155,10 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ JumpIfNotSmi(value, &miss);
// Prepare tail call to StoreIC_ArrayLength.
- __ PopReturnAddressTo(scratch);
+ __ pop(scratch);
__ push(receiver);
__ push(value);
- __ PushReturnAddressFrom(scratch);
+ __ push(scratch); // return address
ExternalReference ref =
ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
@@ -2211,9 +2224,9 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// Slow-case: Handle non-smi or out-of-bounds access to arguments
// by calling the runtime system.
__ bind(&slow);
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx); // Return address.
__ push(rdx);
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx);
__ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
}
@@ -2603,9 +2616,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
if (FLAG_debug_code) {
Condition is_smi = masm->CheckSmi(rax);
__ Check(NegateCondition(is_smi),
- kUnexpectedTypeForRegExpDataFixedArrayExpected);
+ "Unexpected type for RegExp data, FixedArray expected");
__ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
- __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
+ __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
}
// rax: RegExp data (FixedArray)
@@ -2971,7 +2984,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ testb(rbx, Immediate(kIsIndirectStringMask));
- __ Assert(zero, kExternalStringExpectedButNotFound);
+ __ Assert(zero, "external string expected, but not found");
}
__ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
// Move the pointer so that offset-wise, it looks like a sequential string.
@@ -3435,7 +3448,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
}
#ifdef DEBUG
- __ Abort(kUnexpectedFallThroughFromStringComparison);
+ __ Abort("Unexpected fall-through from string comparison");
#endif
__ bind(&check_unequal_objects);
@@ -3473,7 +3486,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
}
// Push arguments below the return address to prepare jump to builtin.
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ push(rdx);
__ push(rax);
@@ -3486,7 +3499,8 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
__ Push(Smi::FromInt(NegativeComparisonResult(cc)));
}
- __ PushReturnAddressFrom(rcx);
+ // Restore return address on the stack.
+ __ push(rcx);
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
@@ -3655,9 +3669,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
// Check for function proxy.
__ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, &non_function);
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ push(rdi); // put proxy as additional argument under return address
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
__ Set(rax, argc_ + 1);
__ Set(rbx, 0);
__ SetCallKind(rcx, CALL_AS_METHOD);
@@ -4261,7 +4275,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ movl(rdi, Immediate(kWordBeforeMapCheckValue));
__ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (check).");
}
__ movq(kScratchRegister,
Operand(kScratchRegister, kOffsetToMapCheckValue));
@@ -4303,7 +4317,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ movl(rax, Immediate(kWordBeforeResultValue));
__ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (mov).");
}
__ Set(rax, 0);
}
@@ -4326,7 +4340,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ movl(rax, Immediate(kWordBeforeResultValue));
__ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
- __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
+ __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
}
}
__ ret(2 * kPointerSize + extra_stack_space);
@@ -4335,9 +4349,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ bind(&slow);
if (HasCallSiteInlineCheck()) {
// Remove extra value from the stack.
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ pop(rax);
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
}
__ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
}
@@ -4390,7 +4404,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharCodeAtGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough to CharCodeAt slow case");
Factory* factory = masm->isolate()->factory();
// Index is not a smi.
@@ -4440,7 +4454,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
+ __ Abort("Unexpected fallthrough from CharCodeAt slow case");
}
@@ -4466,7 +4480,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
- __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough to CharFromCode slow case");
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
@@ -4478,7 +4492,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
call_helper.AfterCall(masm);
__ jmp(&exit_);
- __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
+ __ Abort("Unexpected fallthrough from CharFromCode slow case");
}
@@ -4808,10 +4822,10 @@ void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
Register temp) {
- __ PopReturnAddressTo(temp);
+ __ pop(temp);
__ pop(rdx);
__ pop(rax);
- __ PushReturnAddressFrom(temp);
+ __ push(temp);
}
@@ -5026,7 +5040,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
if (FLAG_debug_code) {
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
__ cmpq(kScratchRegister, candidate);
- __ Assert(equal, kOddballInStringTableIsNotUndefinedOrTheHole);
+ __ Assert(equal, "oddball in string table is not undefined or the hole");
}
__ jmp(&next_probe[i]);
@@ -5515,9 +5529,9 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
// Inline comparison of ASCII strings.
__ IncrementCounter(counters->string_compare_native(), 1);
// Drop arguments from the stack
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ addq(rsp, Immediate(2 * kPointerSize));
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx);
GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
// Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
@@ -5786,10 +5800,10 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
// Handle more complex cases in runtime.
__ bind(&runtime);
- __ PopReturnAddressTo(tmp1);
+ __ pop(tmp1); // Return address.
__ push(left);
__ push(right);
- __ PushReturnAddressFrom(tmp1);
+ __ push(tmp1);
if (equality) {
__ TailCallRuntime(Runtime::kStringEquals, 2, 1);
} else {
@@ -6397,14 +6411,16 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
// the runtime.
__ bind(&slow_elements);
- __ PopReturnAddressTo(rdi);
+ __ pop(rdi); // Pop return address and remember to put back later for tail
+ // call.
__ push(rbx);
__ push(rcx);
__ push(rax);
__ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
__ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
__ push(rdx);
- __ PushReturnAddressFrom(rdi);
+ __ push(rdi); // Return return address so that tail call returns to right
+ // place.
__ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
// Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
@@ -6451,7 +6467,7 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
__ movq(rbx, MemOperand(rbp, parameter_count_offset));
masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
? kPointerSize
: 0;
@@ -6523,7 +6539,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -6586,7 +6602,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
}
// If we reached this point there is a problem.
- __ Abort(kUnexpectedElementsKindInArrayConstructor);
+ __ Abort("Unexpected ElementsKind in array constructor");
}
@@ -6652,9 +6668,9 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
// Will both indicate a NULL and a Smi.
STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
- __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
+ __ Check(not_smi, "Unexpected initial map for Array function");
__ CmpObjectType(rcx, MAP_TYPE, rcx);
- __ Check(equal, kUnexpectedInitialMapForArrayFunction);
+ __ Check(equal, "Unexpected initial map for Array function");
// We should either have undefined in rbx or a valid cell
Label okay_here;
@@ -6662,7 +6678,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ Cmp(rbx, undefined_sentinel);
__ j(equal, &okay_here);
__ Cmp(FieldOperand(rbx, 0), cell_map);
- __ Assert(equal, kExpectedPropertyCellInRegisterRbx);
+ __ Assert(equal, "Expected property cell in register rbx");
__ bind(&okay_here);
}
@@ -6767,9 +6783,9 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
// Will both indicate a NULL and a Smi.
STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
- __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
+ __ Check(not_smi, "Unexpected initial map for Array function");
__ CmpObjectType(rcx, MAP_TYPE, rcx);
- __ Check(equal, kUnexpectedInitialMapForArrayFunction);
+ __ Check(equal, "Unexpected initial map for Array function");
}
// Figure out the right elements kind
@@ -6788,7 +6804,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
__ j(equal, &done);
__ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS));
__ Assert(equal,
- kInvalidElementsKindForInternalArrayOrInternalPackedArray);
+ "Invalid ElementsKind for InternalArray or InternalPackedArray");
__ bind(&done);
}
diff --git a/chromium/v8/src/x64/codegen-x64.cc b/chromium/v8/src/x64/codegen-x64.cc
index a39f14b0757..a823bf2e6d0 100644
--- a/chromium/v8/src/x64/codegen-x64.cc
+++ b/chromium/v8/src/x64/codegen-x64.cc
@@ -394,7 +394,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
if (FLAG_debug_code) {
__ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
- __ Assert(equal, kObjectFoundInSmiOnlyArray);
+ __ Assert(equal, "object found in smi-only array");
}
__ movq(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), r15);
@@ -577,7 +577,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
// Assert that we do not have a cons or slice (indirect strings) here.
// Sequential strings have already been ruled out.
__ testb(result, Immediate(kIsIndirectStringMask));
- __ Assert(zero, kExternalStringExpectedButNotFound);
+ __ Assert(zero, "external string expected, but not found");
}
// Rule out short external strings.
STATIC_CHECK(kShortExternalStringTag != 0);
diff --git a/chromium/v8/src/x64/debug-x64.cc b/chromium/v8/src/x64/debug-x64.cc
index e6bc92950a9..a337b0d052f 100644
--- a/chromium/v8/src/x64/debug-x64.cc
+++ b/chromium/v8/src/x64/debug-x64.cc
@@ -48,10 +48,11 @@ bool BreakLocationIterator::IsDebugBreakAtReturn() {
// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc
// for the precise return instructions sequence.
void BreakLocationIterator::SetDebugBreakAtReturn() {
- ASSERT(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength);
+ ASSERT(Assembler::kJSReturnSequenceLength >=
+ Assembler::kCallInstructionLength);
rinfo()->PatchCodeWithCall(
Isolate::Current()->debug()->debug_break_return()->entry(),
- Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength);
+ Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
}
@@ -81,7 +82,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
ASSERT(IsDebugBreakSlot());
rinfo()->PatchCodeWithCall(
Isolate::Current()->debug()->debug_break_slot()->entry(),
- Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength);
+ Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
}
diff --git a/chromium/v8/src/x64/deoptimizer-x64.cc b/chromium/v8/src/x64/deoptimizer-x64.cc
index e9cf567f7e4..b45e9663e2a 100644
--- a/chromium/v8/src/x64/deoptimizer-x64.cc
+++ b/chromium/v8/src/x64/deoptimizer-x64.cc
@@ -42,7 +42,7 @@ const int Deoptimizer::table_entry_size_ = 10;
int Deoptimizer::patch_size() {
- return Assembler::kCallSequenceLength;
+ return Assembler::kCallInstructionLength;
}
@@ -69,7 +69,7 @@ void Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) {
Address call_address = instruction_start + deopt_data->Pc(i)->value();
// There is room enough to write a long call instruction because we pad
// LLazyBailout instructions with nops if necessary.
- CodePatcher patcher(call_address, Assembler::kCallSequenceLength);
+ CodePatcher patcher(call_address, Assembler::kCallInstructionLength);
patcher.masm()->Call(GetDeoptimizationEntry(isolate, i, LAZY),
RelocInfo::NONE64);
ASSERT(prev_call_address == NULL ||
diff --git a/chromium/v8/src/x64/full-codegen-x64.cc b/chromium/v8/src/x64/full-codegen-x64.cc
index 6333e87bea1..bac4e793b27 100644
--- a/chromium/v8/src/x64/full-codegen-x64.cc
+++ b/chromium/v8/src/x64/full-codegen-x64.cc
@@ -753,9 +753,9 @@ void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
// Check that we're not inside a with or catch context.
__ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
__ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
- __ Check(not_equal, kDeclarationInWithContext);
+ __ Check(not_equal, "Declaration in with context.");
__ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
- __ Check(not_equal, kDeclarationInCatchContext);
+ __ Check(not_equal, "Declaration in catch context.");
}
}
@@ -2192,7 +2192,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
__ Push(Smi::FromInt(resume_mode));
__ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
// Not reached: the runtime call returns elsewhere.
- __ Abort(kGeneratorFailedToResume);
+ __ Abort("Generator failed to resume.");
// Throw error if we attempt to operate on a running generator.
__ bind(&wrong_state);
@@ -2456,7 +2456,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Check for an uninitialized let binding.
__ movq(rdx, location);
__ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
- __ Check(equal, kLetBindingReInitialization);
+ __ Check(equal, "Let binding re-initialization.");
}
// Perform the assignment.
__ movq(location, rax);
@@ -3398,14 +3398,14 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
Register index,
Register value,
uint32_t encoding_mask) {
- __ Check(masm()->CheckSmi(index), kNonSmiIndex);
- __ Check(masm()->CheckSmi(value), kNonSmiValue);
+ __ Check(masm()->CheckSmi(index), "Non-smi index");
+ __ Check(masm()->CheckSmi(value), "Non-smi value");
__ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
- __ Check(less, kIndexIsTooLarge);
+ __ Check(less, "Index is too large");
__ SmiCompare(index, Smi::FromInt(0));
- __ Check(greater_equal, kIndexIsNegative);
+ __ Check(greater_equal, "Index is negative");
__ push(value);
__ movq(value, FieldOperand(string, HeapObject::kMapOffset));
@@ -3413,7 +3413,7 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
__ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
__ cmpq(value, Immediate(encoding_mask));
- __ Check(equal, kUnexpectedStringType);
+ __ Check(equal, "Unexpected string type");
__ pop(value);
}
@@ -3777,7 +3777,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
Handle<FixedArray> jsfunction_result_caches(
isolate()->native_context()->jsfunction_result_caches());
if (jsfunction_result_caches->length() <= cache_id) {
- __ Abort(kAttemptToUseUndefinedCache);
+ __ Abort("Attempt to use undefined cache.");
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
context()->Plug(rax);
return;
@@ -3971,7 +3971,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// scratch, string_length(int32), elements(FixedArray*).
if (generate_debug_code_) {
__ cmpq(index, array_length);
- __ Assert(below, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
+ __ Assert(below, "No empty arrays here in EmitFastAsciiArrayJoin");
}
__ bind(&loop);
__ movq(string, FieldOperand(elements,
@@ -4335,12 +4335,35 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
+ case Token::SUB:
+ EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
+ break;
+
+ case Token::BIT_NOT:
+ EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
+ break;
+
default:
UNREACHABLE();
}
}
+void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
+ const char* comment) {
+ // TODO(svenpanne): Allowing format strings in Comment would be nice here...
+ Comment cmt(masm_, comment);
+ UnaryOpStub stub(expr->op());
+ // UnaryOpStub expects the argument to be in the
+ // accumulator register rax.
+ VisitForAccumulatorValue(expr->expression());
+ SetSourcePosition(expr->position());
+ CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET,
+ expr->UnaryOperationFeedbackId());
+ context()->Plug(rax);
+}
+
+
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
@@ -4796,7 +4819,7 @@ void FullCodeGenerator::EnterFinallyBlock() {
ASSERT(!result_register().is(rdx));
ASSERT(!result_register().is(rcx));
// Cook return address on top of stack (smi encoded Code* delta)
- __ PopReturnAddressTo(rdx);
+ __ pop(rdx);
__ Move(rcx, masm_->CodeObject());
__ subq(rdx, rcx);
__ Integer32ToSmi(rdx, rdx);
diff --git a/chromium/v8/src/x64/ic-x64.cc b/chromium/v8/src/x64/ic-x64.cc
index 4837b9aa9a8..6e238c76ece 100644
--- a/chromium/v8/src/x64/ic-x64.cc
+++ b/chromium/v8/src/x64/ic-x64.cc
@@ -570,10 +570,10 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
__ j(not_zero, &slow);
// Everything is fine, call runtime.
- __ PopReturnAddressTo(rcx);
+ __ pop(rcx);
__ push(rdx); // receiver
__ push(rax); // key
- __ PushReturnAddressFrom(rcx);
+ __ push(rcx); // return address
// Perform tail call to the entry.
__ TailCallExternalReference(
@@ -1369,10 +1369,10 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->load_miss(), 1);
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rax); // receiver
__ push(rcx); // name
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Perform tail call to the entry.
ExternalReference ref =
@@ -1388,10 +1388,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rax); // receiver
__ push(rcx); // name
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
@@ -1408,10 +1408,10 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, ICMissMode miss_mode) {
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->keyed_load_miss(), 1);
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rax); // name
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Perform tail call to the entry.
ExternalReference ref = miss_mode == MISS_FORCE_GENERIC
@@ -1429,10 +1429,10 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rax); // name
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
@@ -1468,11 +1468,11 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rcx); // name
__ push(rax); // value
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Perform tail call to the entry.
ExternalReference ref =
@@ -1512,13 +1512,13 @@ void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx);
__ push(rcx);
__ push(rax);
__ Push(Smi::FromInt(NONE)); // PropertyAttributes
__ Push(Smi::FromInt(strict_mode));
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Do tail-call to runtime routine.
__ TailCallRuntime(Runtime::kSetProperty, 5, 1);
@@ -1534,13 +1534,13 @@ void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rcx); // key
__ push(rax); // value
__ Push(Smi::FromInt(NONE)); // PropertyAttributes
__ Push(Smi::FromInt(strict_mode)); // Strict mode.
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Do tail-call to runtime routine.
__ TailCallRuntime(Runtime::kSetProperty, 5, 1);
@@ -1555,11 +1555,11 @@ void StoreIC::GenerateSlow(MacroAssembler* masm) {
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rcx); // key
__ push(rax); // value
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Do tail-call to runtime routine.
ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate());
@@ -1575,11 +1575,11 @@ void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rcx); // key
__ push(rax); // value
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Do tail-call to runtime routine.
ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
@@ -1595,11 +1595,11 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, ICMissMode miss_mode) {
// -- rsp[0] : return address
// -----------------------------------
- __ PopReturnAddressTo(rbx);
+ __ pop(rbx);
__ push(rdx); // receiver
__ push(rcx); // key
__ push(rax); // value
- __ PushReturnAddressFrom(rbx);
+ __ push(rbx); // return address
// Do tail-call to runtime routine.
ExternalReference ref = miss_mode == MISS_FORCE_GENERIC
diff --git a/chromium/v8/src/x64/lithium-codegen-x64.cc b/chromium/v8/src/x64/lithium-codegen-x64.cc
index abb8c77b5b7..c2207317c18 100644
--- a/chromium/v8/src/x64/lithium-codegen-x64.cc
+++ b/chromium/v8/src/x64/lithium-codegen-x64.cc
@@ -96,7 +96,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
}
-void LChunkBuilder::Abort(BailoutReason reason) {
+void LChunkBuilder::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -278,8 +278,6 @@ bool LCodeGen::GenerateBody() {
instr->Mnemonic());
}
- RecordAndUpdatePosition(instr->position());
-
instr->CompileToNative(this);
}
EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
@@ -333,10 +331,6 @@ bool LCodeGen::GenerateDeferredCode() {
if (deferred_.length() > 0) {
for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
LDeferredCode* code = deferred_[i];
-
- int pos = instructions_->at(code->instruction_index())->position();
- RecordAndUpdatePosition(pos);
-
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",
code->instruction_index(),
@@ -503,57 +497,37 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
break;
}
- int object_index = 0;
- int dematerialized_index = 0;
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
- AddToTranslation(environment,
- translation,
+
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
+ AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- &object_index,
- &dematerialized_index);
+ environment->HasUint32ValueAt(i));
}
}
-void LCodeGen::AddToTranslation(LEnvironment* environment,
- Translation* translation,
+void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer) {
- if (op == LEnvironment::materialization_marker()) {
- int object_index = (*object_index_pointer)++;
- if (environment->ObjectIsDuplicateAt(object_index)) {
- int dupe_of = environment->ObjectDuplicateOfAt(object_index);
- translation->DuplicateObject(dupe_of);
- return;
- }
- int object_length = environment->ObjectLengthAt(object_index);
- if (environment->ObjectIsArgumentsAt(object_index)) {
- translation->BeginArgumentsObject(object_length);
- } else {
- translation->BeginCapturedObject(object_length);
- }
- int dematerialized_index = *dematerialized_index_pointer;
- int env_offset = environment->translation_size() + dematerialized_index;
- *dematerialized_index_pointer += object_length;
- for (int i = 0; i < object_length; ++i) {
- LOperand* value = environment->values()->at(env_offset + i);
- AddToTranslation(environment,
- translation,
- value,
- environment->HasTaggedValueAt(env_offset + i),
- environment->HasUint32ValueAt(env_offset + i),
- object_index_pointer,
- dematerialized_index_pointer);
- }
- return;
- }
-
+ bool is_uint32) {
if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
@@ -687,13 +661,13 @@ void LCodeGen::DeoptimizeIf(Condition cc,
Address entry =
Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
if (entry == NULL) {
- Abort(kBailoutWasNotPrepared);
+ Abort("bailout was not prepared");
return;
}
ASSERT(FLAG_deopt_every_n_times == 0); // Not yet implemented on x64.
- if (info()->ShouldTrapOnDeopt()) {
+ if (FLAG_trap_on_deopt && info()->IsOptimizing()) {
Label done;
if (cc != no_condition) {
__ j(NegateCondition(cc), &done, Label::kNear);
@@ -885,14 +859,6 @@ void LCodeGen::RecordPosition(int position) {
}
-void LCodeGen::RecordAndUpdatePosition(int position) {
- if (position >= 0 && position != old_position_) {
- masm()->positions_recorder()->RecordPosition(position);
- old_position_ = position;
- }
-}
-
-
static const char* LabelType(LLabel* label) {
if (label->is_loop_header()) return " (loop header)";
if (label->is_osr_entry()) return " (OSR entry)";
@@ -1304,7 +1270,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
bool can_overflow =
instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
if (right->IsConstantOperand()) {
- int32_t right_value = ToInteger32(LConstantOperand::cast(right));
+ int right_value = ToInteger32(LConstantOperand::cast(right));
if (right_value == -1) {
__ negl(left);
} else if (right_value == 0) {
@@ -1396,7 +1362,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
ASSERT(left->IsRegister());
if (right->IsConstantOperand()) {
- int32_t right_operand = ToInteger32(LConstantOperand::cast(right));
+ int right_operand = ToInteger32(LConstantOperand::cast(right));
switch (instr->op()) {
case Token::BIT_AND:
__ andl(ToRegister(left), Immediate(right_operand));
@@ -1405,11 +1371,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
__ orl(ToRegister(left), Immediate(right_operand));
break;
case Token::BIT_XOR:
- if (right_operand == int32_t(~0)) {
- __ not_(ToRegister(left));
- } else {
- __ xorl(ToRegister(left), Immediate(right_operand));
- }
+ __ xorl(ToRegister(left), Immediate(right_operand));
break;
default:
UNREACHABLE();
@@ -1480,7 +1442,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
break;
}
} else {
- int32_t value = ToInteger32(LConstantOperand::cast(right));
+ int value = ToInteger32(LConstantOperand::cast(right));
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
switch (instr->op()) {
case Token::ROR:
@@ -1680,7 +1642,7 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
__ cmpq(value, Immediate(encoding == String::ONE_BYTE_ENCODING
? one_byte_seq_type : two_byte_seq_type));
- __ Check(equal, kUnexpectedStringType);
+ __ Check(equal, "Unexpected string type");
__ pop(value);
}
@@ -1694,6 +1656,13 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
}
+void LCodeGen::DoBitNotI(LBitNotI* instr) {
+ LOperand* input = instr->value();
+ ASSERT(input->Equals(instr->result()));
+ __ not_(ToRegister(input));
+}
+
+
void LCodeGen::DoThrow(LThrow* instr) {
__ push(ToRegister(instr->value()));
CallRuntime(Runtime::kThrow, 1, instr);
@@ -1900,13 +1869,6 @@ void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
}
-template<class InstrType>
-void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
- int false_block = instr->FalseDestination(chunk_);
- __ j(cc, chunk_->GetAssemblyLabel(false_block));
-}
-
-
void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
__ int3();
}
@@ -2180,28 +2142,6 @@ void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
}
-void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
- if (instr->hydrogen()->representation().IsTagged()) {
- Register input_reg = ToRegister(instr->object());
- __ Cmp(input_reg, factory()->the_hole_value());
- EmitBranch(instr, equal);
- return;
- }
-
- XMMRegister input_reg = ToDoubleRegister(instr->object());
- __ ucomisd(input_reg, input_reg);
- EmitFalseBranch(instr, parity_odd);
-
- __ subq(rsp, Immediate(kDoubleSize));
- __ movsd(MemOperand(rsp, 0), input_reg);
- __ addq(rsp, Immediate(kDoubleSize));
-
- int offset = sizeof(kHoleNanUpper32);
- __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32));
- EmitBranch(instr, equal);
-}
-
-
Condition LCodeGen::EmitIsObject(Register input,
Label* is_not_object,
Label* is_object) {
@@ -2634,7 +2574,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
// The argument count parameter is a smi
__ SmiToInteger32(reg, reg);
Register return_addr_reg = reg.is(rcx) ? rbx : rcx;
- __ PopReturnAddressTo(return_addr_reg);
+ __ pop(return_addr_reg);
__ shl(reg, Immediate(kPointerSizeLog2));
__ addq(rsp, reg);
__ jmp(return_addr_reg);
@@ -2793,6 +2733,111 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
}
+void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env) {
+ LookupResult lookup(isolate());
+ type->LookupDescriptor(NULL, *name, &lookup);
+ ASSERT(lookup.IsFound() || lookup.IsCacheable());
+ if (lookup.IsField()) {
+ int index = lookup.GetLocalFieldIndexFromMap(*type);
+ int offset = index * kPointerSize;
+ if (index < 0) {
+ // Negative property indices are in-object properties, indexed
+ // from the end of the fixed part of the object.
+ __ movq(result, FieldOperand(object, offset + type->instance_size()));
+ } else {
+ // Non-negative property indices are in the properties array.
+ __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset));
+ __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
+ }
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
+ } else {
+ // Negative lookup.
+ // Check prototypes.
+ Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
+ Heap* heap = type->GetHeap();
+ while (*current != heap->null_value()) {
+ __ LoadHeapObject(result, current);
+ __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
+ Handle<Map>(current->map()));
+ DeoptimizeIf(not_equal, env);
+ current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
+ }
+ __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
+ }
+}
+
+
+// Check for cases where EmitLoadFieldOrConstantFunction needs to walk the
+// prototype chain, which causes unbounded code generation.
+static bool CompactEmit(SmallMapList* list,
+ Handle<String> name,
+ int i,
+ Isolate* isolate) {
+ Handle<Map> map = list->at(i);
+ LookupResult lookup(isolate);
+ map->LookupDescriptor(NULL, *name, &lookup);
+ return lookup.IsField() || lookup.IsConstant();
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+ Register object = ToRegister(instr->object());
+ Register result = ToRegister(instr->result());
+
+ int map_count = instr->hydrogen()->types()->length();
+ bool need_generic = instr->hydrogen()->need_generic();
+
+ if (map_count == 0 && !need_generic) {
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ Handle<String> name = instr->hydrogen()->name();
+ Label done;
+ bool all_are_compact = true;
+ for (int i = 0; i < map_count; ++i) {
+ if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) {
+ all_are_compact = false;
+ break;
+ }
+ }
+ for (int i = 0; i < map_count; ++i) {
+ bool last = (i == map_count - 1);
+ Handle<Map> map = instr->hydrogen()->types()->at(i);
+ Label check_passed;
+ __ CompareMap(object, map, &check_passed);
+ if (last && !need_generic) {
+ DeoptimizeIf(not_equal, instr->environment());
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstantFunction(
+ result, object, map, name, instr->environment());
+ } else {
+ Label next;
+ bool compact = all_are_compact ? true :
+ CompactEmit(instr->hydrogen()->types(), name, i, isolate());
+ __ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
+ __ bind(&check_passed);
+ EmitLoadFieldOrConstantFunction(
+ result, object, map, name, instr->environment());
+ __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
+ __ bind(&next);
+ }
+ }
+ if (need_generic) {
+ __ Move(rcx, name);
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ CallCode(ic, RelocInfo::CODE_TARGET, instr);
+ }
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(rax));
ASSERT(ToRegister(instr->result()).is(rax));
@@ -2859,8 +2904,8 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
if (instr->length()->IsConstantOperand() &&
instr->index()->IsConstantOperand()) {
- int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
- int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length()));
+ int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
int index = (const_length - const_index) + 1;
__ movq(result, Operand(arguments, index * kPointerSize));
} else {
@@ -3047,9 +3092,9 @@ Operand LCodeGen::BuildFastArrayOperand(
Register elements_pointer_reg = ToRegister(elements_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
if (key->IsConstantOperand()) {
- int32_t constant_value = ToInteger32(LConstantOperand::cast(key));
+ int constant_value = ToInteger32(LConstantOperand::cast(key));
if (constant_value & 0xF0000000) {
- Abort(kArrayIndexConstantValueTooBig);
+ Abort("array index constant value too big");
}
return Operand(elements_pointer_reg,
((constant_value + additional_index) << shift_size)
@@ -3387,17 +3432,6 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
}
-void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
- Register input_reg = ToRegister(instr->value());
- __ testq(input_reg, input_reg);
- Label is_positive;
- __ j(not_sign, &is_positive, Label::kNear);
- __ neg(input_reg); // Sets flags.
- DeoptimizeIf(negative, instr->environment());
- __ bind(&is_positive);
-}
-
-
void LCodeGen::DoMathAbs(LMathAbs* instr) {
// Class for deferred case.
class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
@@ -3423,15 +3457,15 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
__ andpd(input_reg, scratch);
} else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
- } else if (r.IsSmi()) {
- EmitSmiMathAbs(instr);
} else { // Tagged case.
DeferredMathAbsTaggedHeapNumber* deferred =
new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
Register input_reg = ToRegister(instr->value());
// Smi check.
__ JumpIfNotSmi(input_reg, deferred->entry());
- EmitSmiMathAbs(instr);
+ __ SmiToInteger32(input_reg, input_reg);
+ EmitIntegerMathAbs(instr);
+ __ Integer32ToSmi(input_reg, input_reg);
__ bind(deferred->exit());
}
}
@@ -4055,7 +4089,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ AssertZeroExtended(reg);
}
if (instr->index()->IsConstantOperand()) {
- int32_t constant_index =
+ int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsSmi()) {
__ Cmp(reg, Smi::FromInt(constant_index));
@@ -4072,7 +4106,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
} else {
Operand length = ToOperand(instr->length());
if (instr->index()->IsConstantOperand()) {
- int32_t constant_index =
+ int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsSmi()) {
__ Cmp(length, Smi::FromInt(constant_index));
@@ -4359,7 +4393,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
// DoStringCharCodeAt above.
STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
if (instr->index()->IsConstantOperand()) {
- int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
__ Push(Smi::FromInt(const_index));
} else {
Register index = ToRegister(instr->index());
@@ -4545,6 +4579,36 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
Register reg = ToRegister(instr->result());
Register tmp = ToRegister(instr->temp());
+ bool convert_hole = false;
+ HValue* change_input = instr->hydrogen()->value();
+ if (change_input->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(change_input);
+ convert_hole = load->UsesMustHandleHole();
+ }
+
+ Label no_special_nan_handling;
+ Label done;
+ if (convert_hole) {
+ XMMRegister input_reg = ToDoubleRegister(instr->value());
+ __ ucomisd(input_reg, input_reg);
+ __ j(parity_odd, &no_special_nan_handling);
+ __ subq(rsp, Immediate(kDoubleSize));
+ __ movsd(MemOperand(rsp, 0), input_reg);
+ __ cmpl(MemOperand(rsp, sizeof(kHoleNanLower32)),
+ Immediate(kHoleNanUpper32));
+ Label canonicalize;
+ __ j(not_equal, &canonicalize);
+ __ addq(rsp, Immediate(kDoubleSize));
+ __ Move(reg, factory()->the_hole_value());
+ __ jmp(&done);
+ __ bind(&canonicalize);
+ __ addq(rsp, Immediate(kDoubleSize));
+ __ Set(kScratchRegister, BitCast<uint64_t>(
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
+ __ movq(input_reg, kScratchRegister);
+ }
+
+ __ bind(&no_special_nan_handling);
DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
if (FLAG_inline_new) {
__ AllocateHeapNumber(reg, tmp, deferred->entry());
@@ -4553,6 +4617,8 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
}
__ bind(deferred->exit());
__ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
+
+ __ bind(&done);
}
@@ -4596,20 +4662,22 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
XMMRegister result_reg,
- bool can_convert_undefined_to_nan,
+ bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
Label load_smi, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
// Heap number map check.
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
- if (!can_convert_undefined_to_nan) {
+ if (!allow_undefined_as_nan) {
DeoptimizeIf(not_equal, env);
} else {
Label heap_number, convert;
@@ -4617,6 +4685,10 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Convert undefined (and hole) to NaN. Compute NaN as 0/0.
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ j(equal, &convert, Label::kNear);
+ __ CompareRoot(input_reg, Heap::kTheHoleValueRootIndex);
+ }
DeoptimizeIf(not_equal, env);
__ bind(&convert);
@@ -4729,12 +4801,19 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
Register input_reg = ToRegister(input);
XMMRegister result_reg = ToDoubleRegister(result);
+ NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
- NumberUntagDMode mode = value->representation().IsSmi()
- ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
+ if (value->type().IsSmi()) {
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
+ }
+ }
EmitNumberUntagD(input_reg, result_reg,
- instr->hydrogen()->can_convert_undefined_to_nan(),
+ instr->hydrogen()->allow_undefined_as_nan(),
instr->hydrogen()->deoptimize_on_minus_zero(),
instr->environment(),
mode);
@@ -4888,64 +4967,31 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
}
-void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
- {
- PushSafepointRegistersScope scope(this);
- __ push(object);
- CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr);
- __ testq(rax, Immediate(kSmiTagMask));
- }
- DeoptimizeIf(zero, instr->environment());
+void LCodeGen::DoCheckMapCommon(Register reg,
+ Handle<Map> map,
+ LInstruction* instr) {
+ Label success;
+ __ CompareMap(reg, map, &success);
+ DeoptimizeIf(not_equal, instr->environment());
+ __ bind(&success);
}
void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
- class DeferredCheckMaps: public LDeferredCode {
- public:
- DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
- : LDeferredCode(codegen), instr_(instr), object_(object) {
- SetExit(check_maps());
- }
- virtual void Generate() {
- codegen()->DoDeferredInstanceMigration(instr_, object_);
- }
- Label* check_maps() { return &check_maps_; }
- virtual LInstruction* instr() { return instr_; }
- private:
- LCheckMaps* instr_;
- Label check_maps_;
- Register object_;
- };
-
if (instr->hydrogen()->CanOmitMapChecks()) return;
-
LOperand* input = instr->value();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
- SmallMapList* map_set = instr->hydrogen()->map_set();
-
- DeferredCheckMaps* deferred = NULL;
- if (instr->hydrogen()->has_migration_target()) {
- deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
- __ bind(deferred->check_maps());
- }
-
Label success;
+ SmallMapList* map_set = instr->hydrogen()->map_set();
for (int i = 0; i < map_set->length() - 1; i++) {
Handle<Map> map = map_set->at(i);
__ CompareMap(reg, map, &success);
__ j(equal, &success);
}
-
Handle<Map> map = map_set->last();
- __ CompareMap(reg, map, &success);
- if (instr->hydrogen()->has_migration_target()) {
- __ j(not_equal, deferred->entry());
- } else {
- DeoptimizeIf(not_equal, instr->environment());
- }
-
+ DoCheckMapCommon(reg, map, instr);
__ bind(&success);
}
@@ -4999,6 +5045,22 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
}
+void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
+ if (instr->hydrogen()->CanOmitPrototypeChecks()) return;
+ Register reg = ToRegister(instr->temp());
+
+ ZoneList<Handle<JSObject> >* prototypes = instr->prototypes();
+ ZoneList<Handle<Map> >* maps = instr->maps();
+
+ ASSERT(prototypes->length() == maps->length());
+
+ for (int i = 0; i < prototypes->length(); i++) {
+ __ LoadHeapObject(reg, prototypes->at(i));
+ DoCheckMapCommon(reg, maps->at(i), instr);
+ }
+}
+
+
void LCodeGen::DoAllocate(LAllocate* instr) {
class DeferredAllocate: public LDeferredCode {
public:
@@ -5338,8 +5400,6 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
if (info()->IsStub() && type == Deoptimizer::EAGER) {
type = Deoptimizer::LAZY;
}
-
- Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
DeoptimizeIf(no_condition, instr->environment(), type);
}
diff --git a/chromium/v8/src/x64/lithium-codegen-x64.h b/chromium/v8/src/x64/lithium-codegen-x64.h
index a74ec7982c4..4286d07de74 100644
--- a/chromium/v8/src/x64/lithium-codegen-x64.h
+++ b/chromium/v8/src/x64/lithium-codegen-x64.h
@@ -67,8 +67,7 @@ class LCodeGen BASE_EMBEDDED {
frame_is_built_(false),
safepoints_(info->zone()),
resolver_(this),
- expected_safepoint_kind_(Safepoint::kSimple),
- old_position_(RelocInfo::kNoPosition) {
+ expected_safepoint_kind_(Safepoint::kSimple) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
}
@@ -103,6 +102,7 @@ class LCodeGen BASE_EMBEDDED {
XMMRegister ToDoubleRegister(LOperand* op) const;
bool IsInteger32Constant(LConstantOperand* op) const;
bool IsSmiConstant(LConstantOperand* op) const;
+ int ToRepresentation(LConstantOperand* op, const Representation& r) const;
int32_t ToInteger32(LConstantOperand* op) const;
Smi* ToSmi(LConstantOperand* op) const;
double ToDouble(LConstantOperand* op) const;
@@ -132,7 +132,8 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
- void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
+
+ void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
// Parallel move support.
void DoParallelMove(LParallelMove* move);
@@ -178,7 +179,7 @@ class LCodeGen BASE_EMBEDDED {
int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
void FPRINTF_CHECKING Comment(const char* format, ...);
void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
@@ -236,6 +237,7 @@ class LCodeGen BASE_EMBEDDED {
CallKind call_kind,
RDIState rdi_state);
+
void RecordSafepointWithLazyDeopt(LInstruction* instr,
SafepointMode safepoint_mode,
int argc);
@@ -246,14 +248,10 @@ class LCodeGen BASE_EMBEDDED {
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition cc, LEnvironment* environment);
void ApplyCheckIf(Condition cc, LBoundsCheck* check);
-
- void AddToTranslation(LEnvironment* environment,
- Translation* translation,
+ void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- int* object_index_pointer,
- int* dematerialized_index_pointer);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -270,7 +268,6 @@ class LCodeGen BASE_EMBEDDED {
uint32_t additional_index = 0);
void EmitIntegerMathAbs(LMathAbs* instr);
- void EmitSmiMathAbs(LMathAbs* instr);
// Support for recording safepoint and position information.
void RecordSafepoint(LPointerMap* pointers,
@@ -283,14 +280,11 @@ class LCodeGen BASE_EMBEDDED {
int arguments,
Safepoint::DeoptMode mode);
void RecordPosition(int position);
- void RecordAndUpdatePosition(int position);
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
template<class InstrType>
void EmitBranch(InstrType instr, Condition cc);
- template<class InstrType>
- void EmitFalseBranch(InstrType instr, Condition cc);
void EmitNumberUntagD(
Register input,
XMMRegister result,
@@ -326,6 +320,12 @@ class LCodeGen BASE_EMBEDDED {
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp);
+ void EmitLoadFieldOrConstantFunction(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env);
+
// Emits code for pushing either a tagged constant, a (non-double)
// register, or a stack slot operand.
void EmitPushTaggedOperand(LOperand* operand);
@@ -382,8 +382,6 @@ class LCodeGen BASE_EMBEDDED {
Safepoint::Kind expected_safepoint_kind_;
- int old_position_;
-
class PushSafepointRegistersScope BASE_EMBEDDED {
public:
explicit PushSafepointRegistersScope(LCodeGen* codegen)
diff --git a/chromium/v8/src/x64/lithium-x64.cc b/chromium/v8/src/x64/lithium-x64.cc
index c058b0df44a..897af2bca14 100644
--- a/chromium/v8/src/x64/lithium-x64.cc
+++ b/chromium/v8/src/x64/lithium-x64.cc
@@ -443,7 +443,7 @@ LPlatformChunk* LChunkBuilder::Build() {
}
-void LCodeGen::Abort(BailoutReason reason) {
+void LCodeGen::Abort(const char* reason) {
info()->set_bailout_reason(reason);
status_ = ABORTED;
}
@@ -601,10 +601,8 @@ LInstruction* LChunkBuilder::DefineFixedDouble(
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
HEnvironment* hydrogen_env = current_block_->last_environment();
int argument_index_accumulator = 0;
- ZoneList<HValue*> objects_to_materialize(0, zone());
instr->set_environment(CreateEnvironment(hydrogen_env,
- &argument_index_accumulator,
- &objects_to_materialize));
+ &argument_index_accumulator));
return instr;
}
@@ -656,7 +654,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
- Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
+ Abort("Out of virtual registers while trying to allocate temp register.");
vreg = 0;
}
operand->set_virtual_register(vreg);
@@ -884,7 +882,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
}
#endif
- instr->set_position(position_);
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
instr = AssignPointerMap(instr);
}
@@ -900,13 +897,11 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LEnvironment* LChunkBuilder::CreateEnvironment(
HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize) {
+ int* argument_index_accumulator) {
if (hydrogen_env == NULL) return NULL;
- LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
- argument_index_accumulator,
- objects_to_materialize);
+ LEnvironment* outer =
+ CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
@@ -921,16 +916,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- int object_index = objects_to_materialize->length();
for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
- LOperand* op;
HValue* value = hydrogen_env->values()->at(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
+ LOperand* op = NULL;
+ if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
+ op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
} else {
@@ -941,33 +936,15 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
value->CheckFlag(HInstruction::kUint32));
}
- for (int i = object_index; i < objects_to_materialize->length(); ++i) {
- HValue* object_to_materialize = objects_to_materialize->at(i);
- int previously_materialized_object = -1;
- for (int prev = 0; prev < i; ++prev) {
- if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
- previously_materialized_object = prev;
- break;
- }
- }
- int length = object_to_materialize->OperandCount();
- bool is_arguments = object_to_materialize->IsArgumentsObject();
- if (previously_materialized_object >= 0) {
- result->AddDuplicateObject(previously_materialized_object);
- continue;
- } else {
- result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
- }
- for (int i = is_arguments ? 1 : 0; i < length; ++i) {
- LOperand* op;
- HValue* value = object_to_materialize->OperandAt(i);
- if (value->IsArgumentsObject() || value->IsCapturedObject()) {
- objects_to_materialize->Add(value, zone());
- op = LEnvironment::materialization_marker();
- } else {
- ASSERT(!value->IsPushArgument());
- op = UseAny(value);
- }
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ LOperand* op = UseAny(value);
result->AddValue(op,
value->representation(),
value->CheckFlag(HInstruction::kUint32));
@@ -1344,6 +1321,16 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
}
+LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
+ ASSERT(instr->value()->representation().IsInteger32());
+ ASSERT(instr->representation().IsInteger32());
+ if (instr->HasNoUses()) return NULL;
+ LOperand* input = UseRegisterAtStart(instr->value());
+ LBitNotI* result = new(zone()) LBitNotI(input);
+ return DefineSameAsFirst(result);
+}
+
+
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
@@ -1612,8 +1599,9 @@ LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
HCompareNumericAndBranch* instr) {
Representation r = instr->representation();
if (r.IsSmiOrInteger32()) {
- ASSERT(instr->left()->representation().Equals(r));
- ASSERT(instr->right()->representation().Equals(r));
+ ASSERT(instr->left()->representation().IsSmiOrInteger32());
+ ASSERT(instr->left()->representation().Equals(
+ instr->right()->representation()));
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
return new(zone()) LCompareNumericAndBranch(left, right);
@@ -1643,13 +1631,6 @@ LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
}
-LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
- HCompareHoleAndBranch* instr) {
- LOperand* object = UseRegisterAtStart(instr->object());
- return new(zone()) LCmpHoleAndBranch(object);
-}
-
-
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
@@ -1764,6 +1745,17 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
+LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
+ return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = Use(instr->length());
@@ -1928,6 +1920,15 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
}
+LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
+ LUnallocated* temp = NULL;
+ if (!instr->CanOmitPrototypeChecks()) temp = TempRegister();
+ LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp);
+ if (instr->CanOmitPrototypeChecks()) return result;
+ return AssignEnvironment(result);
+}
+
+
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckFunction(value));
@@ -1936,16 +1937,10 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
LOperand* value = NULL;
- if (!instr->CanOmitMapChecks()) {
- value = UseRegisterAtStart(instr->value());
- if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
- }
+ if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
LCheckMaps* result = new(zone()) LCheckMaps(value);
- if (!instr->CanOmitMapChecks()) {
- AssignEnvironment(result);
- if (instr->has_migration_target()) return AssignPointerMap(result);
- }
- return result;
+ if (instr->CanOmitMapChecks()) return result;
+ return AssignEnvironment(result);
}
@@ -2065,6 +2060,23 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
}
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+ HLoadNamedFieldPolymorphic* instr) {
+ ASSERT(instr->representation().IsTagged());
+ if (instr->need_generic()) {
+ LOperand* obj = UseFixed(instr->object(), rax);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
+ return MarkAsCall(DefineFixed(result, rax), instr);
+ } else {
+ LOperand* obj = UseRegisterAtStart(instr->object());
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
+ return AssignEnvironment(DefineAsRegister(result));
+ }
+}
+
+
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), rax);
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(object);
@@ -2221,7 +2233,7 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool is_external_location = instr->access().IsExternalMemory() &&
instr->access().offset() == 0;
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
+ bool needs_write_barrier_for_map = !instr->transition().is_null() &&
instr->NeedsWriteBarrierForMap();
LOperand* obj;
@@ -2356,7 +2368,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
- Abort(kTooManySpillSlotsNeededForOSR);
+ Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
@@ -2378,12 +2390,6 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
}
-LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
- // There are no real uses of a captured object.
- return NULL;
-}
-
-
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
info()->MarkAsRequiresFrame();
LOperand* args = UseRegister(instr->arguments());
diff --git a/chromium/v8/src/x64/lithium-x64.h b/chromium/v8/src/x64/lithium-x64.h
index 77bebe64bd7..31e54370e0a 100644
--- a/chromium/v8/src/x64/lithium-x64.h
+++ b/chromium/v8/src/x64/lithium-x64.h
@@ -50,6 +50,7 @@ class LCodeGen;
V(ArithmeticD) \
V(ArithmeticT) \
V(BitI) \
+ V(BitNotI) \
V(BoundsCheck) \
V(Branch) \
V(CallConstantFunction) \
@@ -67,6 +68,7 @@ class LCodeGen;
V(CheckMaps) \
V(CheckMapValue) \
V(CheckNonSmi) \
+ V(CheckPrototypeMaps) \
V(CheckSmi) \
V(ClampDToUint8) \
V(ClampIToUint8) \
@@ -74,7 +76,6 @@ class LCodeGen;
V(ClassOfTestAndBranch) \
V(CompareNumericAndBranch) \
V(CmpObjectEqAndBranch) \
- V(CmpHoleAndBranch) \
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
@@ -127,6 +128,7 @@ class LCodeGen;
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
+ V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(MapEnumLength) \
V(MathAbs) \
@@ -205,11 +207,9 @@ class LCodeGen;
class LInstruction: public ZoneObject {
public:
LInstruction()
- : environment_(NULL),
- hydrogen_value_(NULL),
- bit_field_(IsCallBits::encode(false)) {
- set_position(RelocInfo::kNoPosition);
- }
+ : environment_(NULL),
+ hydrogen_value_(NULL),
+ is_call_(false) { }
virtual ~LInstruction() { }
@@ -249,30 +249,20 @@ class LInstruction: public ZoneObject {
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
- // The 31 bits PositionBits is used to store the int position value. And the
- // position value may be RelocInfo::kNoPosition (-1). The accessor always
- // +1/-1 so that the encoded value of position in bit_field_ is always >= 0
- // and can fit into the 31 bits PositionBits.
- void set_position(int pos) {
- bit_field_ = PositionBits::update(bit_field_, pos + 1);
- }
- int position() { return PositionBits::decode(bit_field_) - 1; }
-
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
- void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
- bool IsCall() const { return IsCallBits::decode(bit_field_); }
+ void MarkAsCall() { is_call_ = true; }
// Interface to the register allocator and iterators.
- bool ClobbersTemps() const { return IsCall(); }
- bool ClobbersRegisters() const { return IsCall(); }
- bool ClobbersDoubleRegisters() const { return IsCall(); }
+ bool ClobbersTemps() const { return is_call_; }
+ bool ClobbersRegisters() const { return is_call_; }
+ bool ClobbersDoubleRegisters() const { return is_call_; }
virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
// Interface to the register allocator and iterators.
- bool IsMarkedAsCall() const { return IsCall(); }
+ bool IsMarkedAsCall() const { return is_call_; }
virtual bool HasResult() const = 0;
virtual LOperand* result() const = 0;
@@ -296,13 +286,10 @@ class LInstruction: public ZoneObject {
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
- class IsCallBits: public BitField<bool, 0, 1> {};
- class PositionBits: public BitField<int, 1, 31> {};
-
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
- int bit_field_;
+ bool is_call_;
};
@@ -838,20 +825,8 @@ class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
LOperand* left() { return inputs_[0]; }
LOperand* right() { return inputs_[1]; }
- DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
-};
-
-
-class LCmpHoleAndBranch: public LControlInstruction<1, 0> {
- public:
- explicit LCmpHoleAndBranch(LOperand* object) {
- inputs_[0] = object;
- }
-
- LOperand* object() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
+ DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch,
+ "cmp-object-eq-and-branch")
};
@@ -1337,6 +1312,18 @@ class LThrow: public LTemplateInstruction<0, 1, 0> {
};
+class LBitNotI: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LBitNotI(LOperand* value) {
+ inputs_[0] = value;
+ }
+
+ LOperand* value() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
+};
+
+
class LAddI: public LTemplateInstruction<1, 2, 0> {
public:
LAddI(LOperand* left, LOperand* right) {
@@ -1478,6 +1465,19 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
};
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+ DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+
+ LOperand* object() { return inputs_[0]; }
+};
+
+
class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadNamedGeneric(LOperand* object) {
@@ -2066,7 +2066,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
virtual void PrintDataTo(StringStream* stream);
- Handle<Map> transition() const { return hydrogen()->transition_map(); }
+ Handle<Map> transition() const { return hydrogen()->transition(); }
Representation representation() const {
return hydrogen()->field_representation();
}
@@ -2262,6 +2262,24 @@ class LCheckMaps: public LTemplateInstruction<0, 1, 0> {
};
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 1> {
+ public:
+ explicit LCheckPrototypeMaps(LOperand* temp) {
+ temps_[0] = temp;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
+ DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
+
+ ZoneList<Handle<JSObject> >* prototypes() const {
+ return hydrogen()->prototypes();
+ }
+ ZoneList<Handle<Map> >* maps() const { return hydrogen()->maps(); }
+};
+
+
class LCheckSmi: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCheckSmi(LOperand* value) {
@@ -2555,7 +2573,7 @@ class LChunkBuilder BASE_EMBEDDED {
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- void Abort(BailoutReason reason);
+ void Abort(const char* reason);
// Methods for getting operands for Use / Define / Temp.
LUnallocated* ToUnallocated(Register reg);
@@ -2641,8 +2659,7 @@ class LChunkBuilder BASE_EMBEDDED {
CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
- int* argument_index_accumulator,
- ZoneList<HValue*>* objects_to_materialize);
+ int* argument_index_accumulator);
void VisitInstruction(HInstruction* current);
diff --git a/chromium/v8/src/x64/macro-assembler-x64.cc b/chromium/v8/src/x64/macro-assembler-x64.cc
index 9c9b1620e58..13d7ddaa685 100644
--- a/chromium/v8/src/x64/macro-assembler-x64.cc
+++ b/chromium/v8/src/x64/macro-assembler-x64.cc
@@ -155,7 +155,7 @@ int MacroAssembler::LoadAddressSize(ExternalReference source) {
}
}
// Size of movq(destination, src);
- return Assembler::kMoveAddressIntoScratchRegisterInstructionLength;
+ return 10;
}
@@ -449,8 +449,8 @@ void MacroAssembler::RecordWrite(Register object,
}
-void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
- if (emit_debug_code()) Check(cc, reason);
+void MacroAssembler::Assert(Condition cc, const char* msg) {
+ if (emit_debug_code()) Check(cc, msg);
}
@@ -466,16 +466,16 @@ void MacroAssembler::AssertFastElements(Register elements) {
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
Heap::kFixedCOWArrayMapRootIndex);
j(equal, &ok, Label::kNear);
- Abort(kJSObjectWithFastElementsMapHasSlowElements);
+ Abort("JSObject with fast elements map has slow elements");
bind(&ok);
}
}
-void MacroAssembler::Check(Condition cc, BailoutReason reason) {
+void MacroAssembler::Check(Condition cc, const char* msg) {
Label L;
j(cc, &L, Label::kNear);
- Abort(reason);
+ Abort(msg);
// Control will not return here.
bind(&L);
}
@@ -508,13 +508,12 @@ void MacroAssembler::NegativeZeroTest(Register result,
}
-void MacroAssembler::Abort(BailoutReason reason) {
+void MacroAssembler::Abort(const char* msg) {
// We want to pass the msg string like a smi to avoid GC
// problems, however msg is not guaranteed to be aligned
// properly. Instead, we pass an aligned pointer that is
// a proper v8 smi, but also pass the alignment difference
// from the real pointer as a smi.
- const char* msg = GetBailoutReason(reason);
intptr_t p1 = reinterpret_cast<intptr_t>(msg);
intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
// Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag.
@@ -839,7 +838,7 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
CompareRoot(return_value, Heap::kNullValueRootIndex);
j(equal, &ok, Label::kNear);
- Abort(kAPICallReturnedInvalidObject);
+ Abort("API call returned invalid object");
bind(&ok);
#endif
@@ -1039,7 +1038,7 @@ void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
RelocInfo::NONE64);
cmpq(dst, kSmiConstantRegister);
if (allow_stub_calls()) {
- Assert(equal, kUninitializedKSmiConstantRegister);
+ Assert(equal, "Uninitialized kSmiConstantRegister");
} else {
Label ok;
j(equal, &ok, Label::kNear);
@@ -1107,7 +1106,7 @@ void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
Label ok;
j(zero, &ok, Label::kNear);
if (allow_stub_calls()) {
- Abort(kInteger32ToSmiFieldWritingToNonSmiLocation);
+ Abort("Integer32ToSmiField writing to non-smi location");
} else {
int3();
}
@@ -1690,12 +1689,12 @@ void MacroAssembler::SmiAdd(Register dst,
if (emit_debug_code()) {
movq(kScratchRegister, src1);
addq(kScratchRegister, src2);
- Check(no_overflow, kSmiAdditionOverflow);
+ Check(no_overflow, "Smi addition overflow");
}
lea(dst, Operand(src1, src2, times_1, 0));
} else {
addq(dst, src2);
- Assert(no_overflow, kSmiAdditionOverflow);
+ Assert(no_overflow, "Smi addition overflow");
}
}
@@ -1727,7 +1726,7 @@ void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
movq(dst, src1);
}
subq(dst, src2);
- Assert(no_overflow, kSmiSubtractionOverflow);
+ Assert(no_overflow, "Smi subtraction overflow");
}
@@ -1759,7 +1758,7 @@ void MacroAssembler::SmiSub(Register dst,
movq(dst, src1);
}
subq(dst, src2);
- Assert(no_overflow, kSmiSubtractionOverflow);
+ Assert(no_overflow, "Smi subtraction overflow");
}
@@ -2156,7 +2155,7 @@ void MacroAssembler::SelectNonSmi(Register dst,
#ifdef DEBUG
if (allow_stub_calls()) { // Check contains a stub call.
Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
- Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi);
+ Check(not_both_smis, "Both registers were smis in SelectNonSmi.");
}
#endif
STATIC_ASSERT(kSmiTag == 0);
@@ -2511,8 +2510,8 @@ void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
int MacroAssembler::CallSize(ExternalReference ext) {
// Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
- return LoadAddressSize(ext) +
- Assembler::kCallScratchRegisterInstructionLength;
+ const int kCallInstructionSize = 3;
+ return LoadAddressSize(ext) + kCallInstructionSize;
}
@@ -2799,9 +2798,9 @@ void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
if (is_uint16(bytes_dropped)) {
ret(bytes_dropped);
} else {
- PopReturnAddressTo(scratch);
+ pop(scratch);
addq(rsp, Immediate(bytes_dropped));
- PushReturnAddressFrom(scratch);
+ push(scratch);
ret(0);
}
}
@@ -2985,7 +2984,7 @@ void MacroAssembler::LoadUint32(XMMRegister dst,
XMMRegister scratch) {
if (FLAG_debug_code) {
cmpq(src, Immediate(0xffffffff));
- Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared);
+ Assert(below_equal, "input GPR is expected to have upper32 cleared");
}
cvtqsi2sd(dst, src);
}
@@ -3034,7 +3033,7 @@ void MacroAssembler::AssertNumber(Register object) {
j(is_smi, &ok, Label::kNear);
Cmp(FieldOperand(object, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
- Check(equal, kOperandIsNotANumber);
+ Check(equal, "Operand is not a number");
bind(&ok);
}
}
@@ -3043,7 +3042,7 @@ void MacroAssembler::AssertNumber(Register object) {
void MacroAssembler::AssertNotSmi(Register object) {
if (emit_debug_code()) {
Condition is_smi = CheckSmi(object);
- Check(NegateCondition(is_smi), kOperandIsASmi);
+ Check(NegateCondition(is_smi), "Operand is a smi");
}
}
@@ -3051,7 +3050,7 @@ void MacroAssembler::AssertNotSmi(Register object) {
void MacroAssembler::AssertSmi(Register object) {
if (emit_debug_code()) {
Condition is_smi = CheckSmi(object);
- Check(is_smi, kOperandIsNotASmi);
+ Check(is_smi, "Operand is not a smi");
}
}
@@ -3059,7 +3058,7 @@ void MacroAssembler::AssertSmi(Register object) {
void MacroAssembler::AssertSmi(const Operand& object) {
if (emit_debug_code()) {
Condition is_smi = CheckSmi(object);
- Check(is_smi, kOperandIsNotASmi);
+ Check(is_smi, "Operand is not a smi");
}
}
@@ -3069,7 +3068,7 @@ void MacroAssembler::AssertZeroExtended(Register int32_register) {
ASSERT(!int32_register.is(kScratchRegister));
movq(kScratchRegister, 0x100000000l, RelocInfo::NONE64);
cmpq(kScratchRegister, int32_register);
- Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
+ Check(above_equal, "32 bit value in register is not zero-extended");
}
}
@@ -3077,12 +3076,12 @@ void MacroAssembler::AssertZeroExtended(Register int32_register) {
void MacroAssembler::AssertString(Register object) {
if (emit_debug_code()) {
testb(object, Immediate(kSmiTagMask));
- Check(not_equal, kOperandIsASmiAndNotAString);
+ Check(not_equal, "Operand is a smi and not a string");
push(object);
movq(object, FieldOperand(object, HeapObject::kMapOffset));
CmpInstanceType(object, FIRST_NONSTRING_TYPE);
pop(object);
- Check(below, kOperandIsNotAString);
+ Check(below, "Operand is not a string");
}
}
@@ -3090,24 +3089,24 @@ void MacroAssembler::AssertString(Register object) {
void MacroAssembler::AssertName(Register object) {
if (emit_debug_code()) {
testb(object, Immediate(kSmiTagMask));
- Check(not_equal, kOperandIsASmiAndNotAName);
+ Check(not_equal, "Operand is a smi and not a name");
push(object);
movq(object, FieldOperand(object, HeapObject::kMapOffset));
CmpInstanceType(object, LAST_NAME_TYPE);
pop(object);
- Check(below_equal, kOperandIsNotAName);
+ Check(below_equal, "Operand is not a name");
}
}
void MacroAssembler::AssertRootValue(Register src,
Heap::RootListIndex root_value_index,
- BailoutReason reason) {
+ const char* message) {
if (emit_debug_code()) {
ASSERT(!src.is(kScratchRegister));
LoadRoot(kScratchRegister, root_value_index);
cmpq(src, kScratchRegister);
- Check(equal, reason);
+ Check(equal, message);
}
}
@@ -3458,7 +3457,7 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) {
isolate()->factory()->undefined_value(),
RelocInfo::EMBEDDED_OBJECT);
cmpq(Operand(rsp, 0), kScratchRegister);
- Check(not_equal, kCodeObjectNotProperlyPatched);
+ Check(not_equal, "code object not properly patched");
}
}
@@ -3467,7 +3466,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
if (emit_debug_code()) {
Move(kScratchRegister, Smi::FromInt(type));
cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
- Check(equal, kStackFrameTypesMustMatch);
+ Check(equal, "stack frame types must match");
}
movq(rsp, rbp);
pop(rbp);
@@ -3568,7 +3567,8 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles) {
// from the caller stack.
lea(rsp, Operand(r15, 1 * kPointerSize));
- PushReturnAddressFrom(rcx);
+ // Push the return address to get ready to return.
+ push(rcx);
LeaveExitFrameEpilogue();
}
@@ -3612,7 +3612,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// When generating debug code, make sure the lexical context is set.
if (emit_debug_code()) {
cmpq(scratch, Immediate(0));
- Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
+ Check(not_equal, "we should not have an empty lexical context");
}
// Load the native context of the current context.
int offset =
@@ -3624,7 +3624,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
if (emit_debug_code()) {
Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
isolate()->factory()->native_context_map());
- Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
+ Check(equal, "JSGlobalObject::native_context should be a native context.");
}
// Check if both contexts are the same.
@@ -3643,12 +3643,12 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
movq(holder_reg,
FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
CompareRoot(holder_reg, Heap::kNullValueRootIndex);
- Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
+ Check(not_equal, "JSGlobalProxy::context() should not be null.");
// Read the first word and compare to native_context_map(),
movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
- Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
+ Check(equal, "JSGlobalObject::native_context should be a native context.");
pop(holder_reg);
}
@@ -3794,7 +3794,7 @@ void MacroAssembler::LoadAllocationTopHelper(Register result,
// Assert that result actually contains top on entry.
Operand top_operand = ExternalOperand(allocation_top);
cmpq(result, top_operand);
- Check(equal, kUnexpectedAllocationTop);
+ Check(equal, "Unexpected allocation top");
#endif
return;
}
@@ -3815,7 +3815,7 @@ void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
AllocationFlags flags) {
if (emit_debug_code()) {
testq(result_end, Immediate(kObjectAlignmentMask));
- Check(zero, kUnalignedAllocationInNewSpace);
+ Check(zero, "Unaligned allocation in new space");
}
ExternalReference allocation_top =
@@ -3862,7 +3862,7 @@ void MacroAssembler::Allocate(int object_size,
// always safe because the limit of the heap is always aligned.
if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
testq(result, Immediate(kDoubleAlignmentMask));
- Check(zero, kAllocationIsNotDoubleAligned);
+ Check(zero, "Allocation is not double aligned");
}
// Calculate new top and bail out if new space is exhausted.
@@ -3941,7 +3941,7 @@ void MacroAssembler::Allocate(Register object_size,
// always safe because the limit of the heap is always aligned.
if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
testq(result, Immediate(kDoubleAlignmentMask));
- Check(zero, kAllocationIsNotDoubleAligned);
+ Check(zero, "Allocation is not double aligned");
}
// Calculate new top and bail out if new space is exhausted.
@@ -3975,7 +3975,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object) {
Operand top_operand = ExternalOperand(new_space_allocation_top);
#ifdef DEBUG
cmpq(object, top_operand);
- Check(below, kUndoAllocationOfNonAllocatedMemory);
+ Check(below, "Undo allocation of non allocated memory");
#endif
movq(top_operand, object);
}
@@ -4165,7 +4165,7 @@ void MacroAssembler::CopyBytes(Register destination,
ASSERT(min_length >= 0);
if (emit_debug_code()) {
cmpl(length, Immediate(min_length));
- Assert(greater_equal, kInvalidMinLength);
+ Assert(greater_equal, "Invalid min_length");
}
Label loop, done, short_string, short_loop;
@@ -4249,7 +4249,7 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
if (emit_debug_code()) {
CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
Heap::kWithContextMapRootIndex);
- Check(not_equal, kVariableResolvedToWithContext);
+ Check(not_equal, "Variable resolved to with context.");
}
}
@@ -4340,7 +4340,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
jmp(&ok);
bind(&fail);
- Abort(kGlobalFunctionsMustHaveInitialMap);
+ Abort("Global functions must have initial map");
bind(&ok);
}
}
diff --git a/chromium/v8/src/x64/macro-assembler-x64.h b/chromium/v8/src/x64/macro-assembler-x64.h
index 61abc206e10..e611c8ae279 100644
--- a/chromium/v8/src/x64/macro-assembler-x64.h
+++ b/chromium/v8/src/x64/macro-assembler-x64.h
@@ -823,10 +823,6 @@ class MacroAssembler: public Assembler {
void Drop(int stack_elements);
void Call(Label* target) { call(target); }
- void Push(Register src) { push(src); }
- void Pop(Register dst) { pop(dst); }
- void PushReturnAddressFrom(Register src) { push(src); }
- void PopReturnAddressTo(Register dst) { pop(dst); }
// Control Flow
void Jump(Address destination, RelocInfo::Mode rmode);
@@ -841,7 +837,7 @@ class MacroAssembler: public Assembler {
// The size of the code generated for different call instructions.
int CallSize(Address destination, RelocInfo::Mode rmode) {
- return kCallSequenceLength;
+ return kCallInstructionLength;
}
int CallSize(ExternalReference ext);
int CallSize(Handle<Code> code_object) {
@@ -1006,7 +1002,7 @@ class MacroAssembler: public Assembler {
// enabled via --debug-code.
void AssertRootValue(Register src,
Heap::RootListIndex root_value_index,
- BailoutReason reason);
+ const char* message);
// ---------------------------------------------------------------------------
// Exception handling
@@ -1323,15 +1319,15 @@ class MacroAssembler: public Assembler {
// Calls Abort(msg) if the condition cc is not satisfied.
// Use --debug_code to enable.
- void Assert(Condition cc, BailoutReason reason);
+ void Assert(Condition cc, const char* msg);
void AssertFastElements(Register elements);
// Like Assert(), but always enabled.
- void Check(Condition cc, BailoutReason reason);
+ void Check(Condition cc, const char* msg);
// Print a message to stdout and abort execution.
- void Abort(BailoutReason msg);
+ void Abort(const char* msg);
// Check that the stack is aligned.
void CheckStackAlignment();
diff --git a/chromium/v8/src/x64/regexp-macro-assembler-x64.cc b/chromium/v8/src/x64/regexp-macro-assembler-x64.cc
index dcd317c666e..106ffb76da5 100644
--- a/chromium/v8/src/x64/regexp-macro-assembler-x64.cc
+++ b/chromium/v8/src/x64/regexp-macro-assembler-x64.cc
@@ -397,7 +397,7 @@ void RegExpMacroAssemblerX64::CheckNotBackReference(
// Fail on partial or illegal capture (start of capture after end of capture).
// This must not happen (no back-reference can reference a capture that wasn't
// closed before in the reg-exp).
- __ Check(greater_equal, kInvalidCaptureReferenced);
+ __ Check(greater_equal, "Invalid capture referenced");
// Succeed on empty capture (including non-participating capture)
__ j(equal, &fallthrough);
diff --git a/chromium/v8/src/x64/stub-cache-x64.cc b/chromium/v8/src/x64/stub-cache-x64.cc
index 34a557bd1af..39ff656ec45 100644
--- a/chromium/v8/src/x64/stub-cache-x64.cc
+++ b/chromium/v8/src/x64/stub-cache-x64.cc
@@ -830,11 +830,11 @@ void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
object->map()->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
- __ PopReturnAddressTo(scratch1);
+ __ pop(scratch1); // Return address.
__ push(receiver_reg);
__ Push(transition);
__ push(value_reg);
- __ PushReturnAddressFrom(scratch1);
+ __ push(scratch1);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
masm->isolate()),
@@ -1284,7 +1284,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
Handle<ExecutableAccessorInfo> callback) {
// Insert additional parameters into the stack frame above return address.
ASSERT(!scratch4().is(reg));
- __ PopReturnAddressTo(scratch4());
+ __ pop(scratch4()); // Get return address to place it below.
__ push(receiver()); // receiver
__ push(reg); // holder
@@ -1324,7 +1324,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
ASSERT(!name_arg.is(scratch4()));
__ movq(name_arg, rsp);
- __ PushReturnAddressFrom(scratch4());
+ __ push(scratch4()); // Restore return address.
// v8::Arguments::values_ and handler for name.
const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -1444,10 +1444,10 @@ void BaseLoadStubCompiler::GenerateLoadInterceptor(
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
- __ PopReturnAddressTo(scratch2());
+ __ pop(scratch2()); // save old return address
PushInterceptorArguments(masm(), receiver(), holder_reg,
this->name(), interceptor_holder);
- __ PushReturnAddressFrom(scratch2());
+ __ push(scratch2()); // restore old return address
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
@@ -2246,25 +2246,26 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Label not_smi;
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfNotSmi(rax, &not_smi);
+ __ SmiToInteger32(rax, rax);
- // Branchless abs implementation, refer to below:
- // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
// Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
// otherwise.
- __ movq(rbx, rax);
- __ sar(rbx, Immediate(kBitsPerPointer - 1));
+ __ movl(rbx, rax);
+ __ sarl(rbx, Immediate(kBitsPerInt - 1));
// Do bitwise not or do nothing depending on ebx.
- __ xor_(rax, rbx);
+ __ xorl(rax, rbx);
// Add 1 or do nothing depending on ebx.
- __ subq(rax, rbx);
+ __ subl(rax, rbx);
// If the result is still negative, go to the slow case.
// This only happens for the most negative smi.
Label slow;
__ j(negative, &slow);
+ // Smi case done.
+ __ Integer32ToSmi(rax, rax);
__ ret(2 * kPointerSize);
// Check if the argument is a heap number and load its value.
@@ -2649,12 +2650,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
- __ PopReturnAddressTo(scratch1());
+ __ pop(scratch1()); // remove the return address
__ push(receiver());
__ Push(callback); // callback info
__ Push(name);
__ push(value());
- __ PushReturnAddressFrom(scratch1());
+ __ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@@ -2716,12 +2717,12 @@ void StoreStubCompiler::GenerateStoreViaSetter(
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> object,
Handle<Name> name) {
- __ PopReturnAddressTo(scratch1());
+ __ pop(scratch1()); // remove the return address
__ push(receiver());
__ push(this->name());
__ push(value());
__ Push(Smi::FromInt(strict_mode()));
- __ PushReturnAddressFrom(scratch1());
+ __ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@@ -2937,7 +2938,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ j(equal, &miss);
} else if (FLAG_debug_code) {
__ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
- __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
+ __ Check(not_equal, "DontDelete cells can't contain the hole");
}
HandlerFrontendFooter(name, &success, &miss);
diff --git a/chromium/v8/src/zone-inl.h b/chromium/v8/src/zone-inl.h
index f257382a2db..49e7626f74e 100644
--- a/chromium/v8/src/zone-inl.h
+++ b/chromium/v8/src/zone-inl.h
@@ -109,12 +109,6 @@ void* ZoneList<T>::operator new(size_t size, Zone* zone) {
}
-template <typename T>
-void* ZoneSplayTree<T>::operator new(size_t size, Zone* zone) {
- return zone->New(static_cast<int>(size));
-}
-
-
} } // namespace v8::internal
#endif // V8_ZONE_INL_H_
diff --git a/chromium/v8/src/zone.h b/chromium/v8/src/zone.h
index bd7cc39b0c4..a12ed793123 100644
--- a/chromium/v8/src/zone.h
+++ b/chromium/v8/src/zone.h
@@ -177,7 +177,6 @@ struct ZoneAllocationPolicy {
explicit ZoneAllocationPolicy(Zone* zone) : zone_(zone) { }
INLINE(void* New(size_t size));
INLINE(static void Delete(void *pointer)) { }
- Zone* zone() { return zone_; }
private:
Zone* zone_;
@@ -202,7 +201,7 @@ class ZoneList: public List<T, ZoneAllocationPolicy> {
ZoneList(const ZoneList<T>& other, Zone* zone)
: List<T, ZoneAllocationPolicy>(other.length(),
ZoneAllocationPolicy(zone)) {
- AddAll(other, zone);
+ AddAll(other, ZoneAllocationPolicy(zone));
}
// We add some convenience wrappers so that we can pass in a Zone
@@ -210,7 +209,8 @@ class ZoneList: public List<T, ZoneAllocationPolicy> {
INLINE(void Add(const T& element, Zone* zone)) {
List<T, ZoneAllocationPolicy>::Add(element, ZoneAllocationPolicy(zone));
}
- INLINE(void AddAll(const List<T, ZoneAllocationPolicy>& other, Zone* zone)) {
+ INLINE(void AddAll(const List<T, ZoneAllocationPolicy>& other,
+ Zone* zone)) {
List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
}
INLINE(void AddAll(const Vector<T>& other, Zone* zone)) {
@@ -246,11 +246,6 @@ class ZoneSplayTree: public SplayTree<Config, ZoneAllocationPolicy> {
explicit ZoneSplayTree(Zone* zone)
: SplayTree<Config, ZoneAllocationPolicy>(ZoneAllocationPolicy(zone)) {}
~ZoneSplayTree();
-
- INLINE(void* operator new(size_t size, Zone* zone));
-
- void operator delete(void* pointer) { UNREACHABLE(); }
- void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
};
diff --git a/chromium/v8/tools/gcmole/Makefile b/chromium/v8/tools/gcmole/Makefile
index 764245caf61..23c029c2dc3 100644
--- a/chromium/v8/tools/gcmole/Makefile
+++ b/chromium/v8/tools/gcmole/Makefile
@@ -40,4 +40,4 @@ libgcmole.so: gcmole.cc
-shared -o libgcmole.so gcmole.cc
clean:
- rm -f libgcmole.so
+ rm libgcmole.so
diff --git a/chromium/v8/tools/gcmole/bootstrap.sh b/chromium/v8/tools/gcmole/bootstrap.sh
deleted file mode 100755
index baa0b1f5f54..00000000000
--- a/chromium/v8/tools/gcmole/bootstrap.sh
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env bash
-
-# 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 script will build libgcmole.so.
-
-CLANG_RELEASE=2.9
-
-THIS_DIR="$(dirname "${0}")"
-LLVM_DIR="${THIS_DIR}/../../third_party/llvm"
-CLANG_DIR="${LLVM_DIR}/tools/clang"
-
-LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
-
-# Die if any command dies.
-set -e
-
-OS="$(uname -s)"
-
-# Xcode and clang don't get along when predictive compilation is enabled.
-# http://crbug.com/96315
-if [[ "${OS}" = "Darwin" ]] && xcodebuild -version | grep -q 'Xcode 3.2' ; then
- XCONF=com.apple.Xcode
- if [[ "${GYP_GENERATORS}" != "make" ]] && \
- [ "$(defaults read "${XCONF}" EnablePredictiveCompilation)" != "0" ]; then
- echo
- echo " HEARKEN!"
- echo "You're using Xcode3 and you have 'Predictive Compilation' enabled."
- echo "This does not work well with clang (http://crbug.com/96315)."
- echo "Disable it in Preferences->Building (lower right), or run"
- echo " defaults write ${XCONF} EnablePredictiveCompilation -boolean NO"
- echo "while Xcode is not running."
- echo
- fi
-
- SUB_VERSION=$(xcodebuild -version | sed -Ene 's/Xcode 3\.2\.([0-9]+)/\1/p')
- if [[ "${SUB_VERSION}" < 6 ]]; then
- echo
- echo " YOUR LD IS BUGGY!"
- echo "Please upgrade Xcode to at least 3.2.6."
- echo
- fi
-fi
-
-echo Getting LLVM r"${CLANG_RELEASE}" in "${LLVM_DIR}"
-if ! svn co --force \
- "${LLVM_REPO_URL}/llvm/branches/release_${CLANG_RELEASE/./}" \
- "${LLVM_DIR}"; then
- echo Checkout failed, retrying
- rm -rf "${LLVM_DIR}"
- svn co --force \
- "${LLVM_REPO_URL}/llvm/branches/release_${CLANG_RELEASE/./}" \
- "${LLVM_DIR}"
-fi
-
-echo Getting clang r"${CLANG_RELEASE}" in "${CLANG_DIR}"
-svn co --force \
- "${LLVM_REPO_URL}/cfe/branches/release_${CLANG_RELEASE/./}" \
- "${CLANG_DIR}"
-
-# Echo all commands
-set -x
-
-NUM_JOBS=3
-if [[ "${OS}" = "Linux" ]]; then
- NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)"
-elif [ "${OS}" = "Darwin" ]; then
- NUM_JOBS="$(sysctl -n hw.ncpu)"
-fi
-
-# Build clang.
-cd "${LLVM_DIR}"
-if [[ ! -f ./config.status ]]; then
- ../llvm/configure \
- --enable-optimized \
- --disable-threads \
- --disable-pthreads \
- --without-llvmgcc \
- --without-llvmgxx
-fi
-
-MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
-STRIP_FLAGS=
-if [ "${OS}" = "Darwin" ]; then
- # See http://crbug.com/256342
- STRIP_FLAGS=-x
-fi
-strip ${STRIP_FLAGS} Release/bin/clang
-cd -
-
-# Build libgcmole.so
-make -C "${THIS_DIR}" clean
-make -C "${THIS_DIR}" LLVM_SRC_ROOT="${LLVM_DIR}" libgcmole.so
-
-set +x
-
-echo
-echo You can now run gcmole using this command:
-echo
-echo CLANG_BIN=\"third_party/llvm/Release/bin\" lua tools/gcmole/gcmole.lua
-echo
diff --git a/chromium/v8/tools/gcmole/gcmole.lua b/chromium/v8/tools/gcmole/gcmole.lua
index aa9324756ac..66aff942a49 100644
--- a/chromium/v8/tools/gcmole/gcmole.lua
+++ b/chromium/v8/tools/gcmole/gcmole.lua
@@ -103,10 +103,7 @@ local function MakeClangCommandLine(plugin, plugin_args, triple, arch_define)
.. " -triple " .. triple
.. " -D" .. arch_define
.. " -DENABLE_DEBUGGER_SUPPORT"
- .. " -DV8_I18N_SUPPORT"
.. " -Isrc"
- .. " -Ithird_party/icu/source/common"
- .. " -Ithird_party/icu/source/i18n"
end
function InvokeClangPluginForEachFile(filenames, cfg, func)
diff --git a/chromium/v8/tools/grokdump.py b/chromium/v8/tools/grokdump.py
index 12ccefdef74..9719376d7f4 100755
--- a/chromium/v8/tools/grokdump.py
+++ b/chromium/v8/tools/grokdump.py
@@ -40,7 +40,6 @@ import re
import struct
import sys
import types
-import v8heapconst
USAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
@@ -164,11 +163,6 @@ def FullDump(reader, heap):
reader.ForEachMemoryRegion(dump_region)
-# Heap constants generated by 'make grokdump' in v8heapconst module.
-INSTANCE_TYPES = v8heapconst.INSTANCE_TYPES
-KNOWN_MAPS = v8heapconst.KNOWN_MAPS
-KNOWN_OBJECTS = v8heapconst.KNOWN_OBJECTS
-
# Set of structures and constants that describe the layout of minidump
# files. Based on MSDN and Google Breakpad.
@@ -760,14 +754,6 @@ class MinidumpReader(object):
elif self.arch == MD_CPU_ARCHITECTURE_X86:
return self.exception_context.esp
- def ExceptionFP(self):
- if self.arch == MD_CPU_ARCHITECTURE_AMD64:
- return self.exception_context.rbp
- elif self.arch == MD_CPU_ARCHITECTURE_ARM:
- return None
- elif self.arch == MD_CPU_ARCHITECTURE_X86:
- return self.exception_context.ebp
-
def FormatIntPtr(self, value):
if self.arch == MD_CPU_ARCHITECTURE_AMD64:
return "%016x" % value
@@ -848,6 +834,262 @@ class MinidumpReader(object):
return "%s+0x%x" % (symbol.name, diff)
+
+# List of V8 instance types. Obtained by adding the code below to any .cc file.
+#
+# #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", T, #T);
+# struct P {
+# P() {
+# printf("INSTANCE_TYPES = {\n");
+# INSTANCE_TYPE_LIST(DUMP_TYPE)
+# printf("}\n");
+# }
+# };
+# static P p;
+INSTANCE_TYPES = {
+ 0: "STRING_TYPE",
+ 4: "ASCII_STRING_TYPE",
+ 1: "CONS_STRING_TYPE",
+ 5: "CONS_ASCII_STRING_TYPE",
+ 3: "SLICED_STRING_TYPE",
+ 2: "EXTERNAL_STRING_TYPE",
+ 6: "EXTERNAL_ASCII_STRING_TYPE",
+ 10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
+ 18: "SHORT_EXTERNAL_STRING_TYPE",
+ 22: "SHORT_EXTERNAL_ASCII_STRING_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_WEAK_SET_TYPE",
+ 185: "JS_REGEXP_TYPE",
+ 186: "JS_FUNCTION_TYPE",
+ 170: "JS_FUNCTION_PROXY_TYPE",
+ 165: "DEBUG_INFO_TYPE",
+ 166: "BREAK_POINT_INFO_TYPE",
+}
+
+
+# List of known V8 maps. Used to determine the instance type and name
+# for maps that are part of the root-set and hence on the first page of
+# the map-space. Obtained by adding the code below to an IA32 release
+# build with enabled snapshots to the end of the Isolate::Init method.
+#
+# #define ROOT_LIST_CASE(type, name, camel_name) \
+# if (o == heap_.name()) n = #camel_name;
+# #define STRUCT_LIST_CASE(upper_name, camel_name, name) \
+# if (o == heap_.name##_map()) n = #camel_name "Map";
+# HeapObjectIterator it(heap_.map_space());
+# printf("KNOWN_MAPS = {\n");
+# for (Object* o = it.Next(); o != NULL; o = it.Next()) {
+# Map* m = Map::cast(o);
+# const char* n = "";
+# intptr_t p = reinterpret_cast<intptr_t>(m) & 0xfffff;
+# int t = m->instance_type();
+# ROOT_LIST(ROOT_LIST_CASE)
+# STRUCT_LIST(STRUCT_LIST_CASE)
+# printf(" 0x%05x: (%d, \"%s\"),\n", p, t, n);
+# }
+# printf("}\n");
+KNOWN_MAPS = {
+ 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: (4, "AsciiStringMap"),
+ 0x083a1: (1, "ConsStringMap"),
+ 0x083c9: (5, "ConsAsciiStringMap"),
+ 0x083f1: (3, "SlicedStringMap"),
+ 0x08419: (7, "SlicedAsciiStringMap"),
+ 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"),
+}
+
+
+# List of known V8 objects. Used to determine name for objects that are
+# part of the root-set and hence on the first page of various old-space
+# paged. Obtained by adding the code below to an IA32 release build with
+# enabled snapshots to the end of the Isolate::Init method.
+#
+# #define ROOT_LIST_CASE(type, name, camel_name) \
+# if (o == heap_.name()) n = #camel_name;
+# OldSpaces spit(heap());
+# printf("KNOWN_OBJECTS = {\n");
+# for (PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
+# HeapObjectIterator it(s);
+# const char* sname = AllocationSpaceName(s->identity());
+# for (Object* o = it.Next(); o != NULL; o = it.Next()) {
+# const char* n = NULL;
+# intptr_t p = reinterpret_cast<intptr_t>(o) & 0xfffff;
+# ROOT_LIST(ROOT_LIST_CASE)
+# if (n != NULL) {
+# printf(" (\"%s\", 0x%05x): \"%s\",\n", sname, p, n);
+# }
+# }
+# }
+# printf("}\n");
+KNOWN_OBJECTS = {
+ ("OLD_POINTER_SPACE", 0x08081): "NullValue",
+ ("OLD_POINTER_SPACE", 0x08091): "UndefinedValue",
+ ("OLD_POINTER_SPACE", 0x080a1): "InstanceofCacheMap",
+ ("OLD_POINTER_SPACE", 0x080b1): "TrueValue",
+ ("OLD_POINTER_SPACE", 0x080c1): "FalseValue",
+ ("OLD_POINTER_SPACE", 0x080d1): "NoInterceptorResultSentinel",
+ ("OLD_POINTER_SPACE", 0x080e1): "ArgumentsMarker",
+ ("OLD_POINTER_SPACE", 0x080f1): "NumberStringCache",
+ ("OLD_POINTER_SPACE", 0x088f9): "SingleCharacterStringCache",
+ ("OLD_POINTER_SPACE", 0x08b01): "StringSplitCache",
+ ("OLD_POINTER_SPACE", 0x08f09): "RegExpMultipleCache",
+ ("OLD_POINTER_SPACE", 0x09311): "TerminationException",
+ ("OLD_POINTER_SPACE", 0x09321): "MessageListeners",
+ ("OLD_POINTER_SPACE", 0x0933d): "CodeStubs",
+ ("OLD_POINTER_SPACE", 0x09fa5): "NonMonomorphicCache",
+ ("OLD_POINTER_SPACE", 0x0a5b9): "PolymorphicCodeCache",
+ ("OLD_POINTER_SPACE", 0x0a5c1): "NativesSourceCache",
+ ("OLD_POINTER_SPACE", 0x0a601): "EmptyScript",
+ ("OLD_POINTER_SPACE", 0x0a63d): "IntrinsicFunctionNames",
+ ("OLD_POINTER_SPACE", 0x0d659): "ObservationState",
+ ("OLD_POINTER_SPACE", 0x27415): "SymbolTable",
+ ("OLD_DATA_SPACE", 0x08099): "EmptyDescriptorArray",
+ ("OLD_DATA_SPACE", 0x080a1): "EmptyFixedArray",
+ ("OLD_DATA_SPACE", 0x080a9): "NanValue",
+ ("OLD_DATA_SPACE", 0x08125): "EmptyByteArray",
+ ("OLD_DATA_SPACE", 0x0812d): "EmptyString",
+ ("OLD_DATA_SPACE", 0x08259): "InfinityValue",
+ ("OLD_DATA_SPACE", 0x08265): "MinusZeroValue",
+ ("OLD_DATA_SPACE", 0x08271): "PrototypeAccessors",
+ ("CODE_SPACE", 0x0aea1): "JsEntryCode",
+ ("CODE_SPACE", 0x0b5c1): "JsConstructEntryCode",
+}
+
+
class Printer(object):
"""Printer with indentation support."""
@@ -1959,15 +2201,11 @@ def AnalyzeMinidump(options, minidump_name):
print "Kthxbye."
elif not options.command:
if reader.exception is not None:
- frame_pointer = reader.ExceptionFP()
print "Annotated stack (from exception.esp to bottom):"
for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
maybe_address = reader.ReadUIntPtr(slot)
heap_object = heap.FindObject(maybe_address)
maybe_symbol = reader.FindSymbol(maybe_address)
- if slot == frame_pointer:
- maybe_symbol = "<---- frame pointer"
- frame_pointer = maybe_address
print "%s: %s %s" % (reader.FormatIntPtr(slot),
reader.FormatIntPtr(maybe_address),
maybe_symbol or "")
diff --git a/chromium/v8/tools/gyp/v8.gyp b/chromium/v8/tools/gyp/v8.gyp
index 66376c17df5..bdbc7163df4 100644
--- a/chromium/v8/tools/gyp/v8.gyp
+++ b/chromium/v8/tools/gyp/v8.gyp
@@ -290,7 +290,6 @@
'../../src/double.h',
'../../src/dtoa.cc',
'../../src/dtoa.h',
- '../../src/effects.h',
'../../src/elements-kind.cc',
'../../src/elements-kind.h',
'../../src/elements.cc',
@@ -823,14 +822,20 @@
}],
['v8_enable_i18n_support==1', {
'sources': [
- '../../src/i18n.cc',
- '../../src/i18n.h',
'../../src/extensions/i18n/break-iterator.cc',
'../../src/extensions/i18n/break-iterator.h',
+ '../../src/extensions/i18n/collator.cc',
+ '../../src/extensions/i18n/collator.h',
+ '../../src/extensions/i18n/date-format.cc',
+ '../../src/extensions/i18n/date-format.h',
'../../src/extensions/i18n/i18n-extension.cc',
'../../src/extensions/i18n/i18n-extension.h',
'../../src/extensions/i18n/i18n-utils.cc',
'../../src/extensions/i18n/i18n-utils.h',
+ '../../src/extensions/i18n/locale.cc',
+ '../../src/extensions/i18n/locale.h',
+ '../../src/extensions/i18n/number-format.cc',
+ '../../src/extensions/i18n/number-format.h',
],
'dependencies': [
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',
@@ -902,8 +907,7 @@
'../../src/typedarray.js',
'../../src/generator.js',
'../../src/array-iterator.js',
- '../../src/harmony-string.js',
- '../../src/harmony-array.js',
+ '../../src/harmony-string.js'
],
'i18n_library_files': [
'../../src/extensions/i18n/header.js',
diff --git a/chromium/v8/tools/run-tests.py b/chromium/v8/tools/run-tests.py
index 48682d4444e..761d03fe335 100755
--- a/chromium/v8/tools/run-tests.py
+++ b/chromium/v8/tools/run-tests.py
@@ -94,9 +94,6 @@ def BuildOptions():
default=False, action="store_true")
result.add_option("--cat", help="Print the source of the tests",
default=False, action="store_true")
- result.add_option("--flaky-tests",
- help="Regard tests marked as flaky (run|skip|dontcare)",
- default="dontcare")
result.add_option("--command-prefix",
help="Prepended to each shell command used to run a test",
default="")
@@ -207,9 +204,6 @@ def ProcessOptions(options):
# This is OK for distributed running, so we don't need to set no_network.
options.command_prefix = (["python", "-u", run_valgrind] +
options.command_prefix)
- if not options.flaky_tests in ["run", "skip", "dontcare"]:
- print "Unknown flaky test mode %s" % options.flaky_tests
- return False
return True
@@ -321,7 +315,7 @@ def Execute(arch, mode, args, options, suites, workspace):
if len(args) > 0:
s.FilterTestCasesByArgs(args)
all_tests += s.tests
- s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests)
+ s.FilterTestCasesByStatus(options.warn_unused)
if options.cat:
verbose.PrintTestSource(s.tests)
continue
diff --git a/chromium/v8/tools/testrunner/local/old_statusfile.py b/chromium/v8/tools/testrunner/local/old_statusfile.py
index d634e3ec955..a9a62036ec4 100644
--- a/chromium/v8/tools/testrunner/local/old_statusfile.py
+++ b/chromium/v8/tools/testrunner/local/old_statusfile.py
@@ -37,7 +37,6 @@ OKAY = 'OKAY'
TIMEOUT = 'TIMEOUT'
CRASH = 'CRASH'
SLOW = 'SLOW'
-FLAKY = 'FLAKY'
# These are just for the status files and are mapped below in DEFS:
FAIL_OK = 'FAIL_OK'
PASS_OR_FAIL = 'PASS_OR_FAIL'
@@ -49,7 +48,6 @@ KEYWORDS = {SKIP: SKIP,
TIMEOUT: TIMEOUT,
CRASH: CRASH,
SLOW: SLOW,
- FLAKY: FLAKY,
FAIL_OK: FAIL_OK,
PASS_OR_FAIL: PASS_OR_FAIL}
diff --git a/chromium/v8/tools/testrunner/local/statusfile.py b/chromium/v8/tools/testrunner/local/statusfile.py
index 1d30fe3d3c1..634fe6a08a8 100644
--- a/chromium/v8/tools/testrunner/local/statusfile.py
+++ b/chromium/v8/tools/testrunner/local/statusfile.py
@@ -42,7 +42,6 @@ OKAY = "OKAY"
TIMEOUT = "TIMEOUT"
CRASH = "CRASH"
SLOW = "SLOW"
-FLAKY = "FLAKY"
# These are just for the status files and are mapped below in DEFS:
FAIL_OK = "FAIL_OK"
PASS_OR_FAIL = "PASS_OR_FAIL"
@@ -50,7 +49,7 @@ PASS_OR_FAIL = "PASS_OR_FAIL"
ALWAYS = "ALWAYS"
KEYWORDS = {}
-for key in [SKIP, FAIL, PASS, OKAY, TIMEOUT, CRASH, SLOW, FLAKY, FAIL_OK,
+for key in [SKIP, FAIL, PASS, OKAY, TIMEOUT, CRASH, SLOW, FAIL_OK,
PASS_OR_FAIL, ALWAYS]:
KEYWORDS[key] = key
@@ -69,10 +68,6 @@ def DoSkip(outcomes):
def IsFlaky(outcomes):
- return FLAKY in outcomes
-
-
-def IsPassOrFail(outcomes):
return ((PASS in outcomes) and (FAIL in outcomes) and
(not CRASH in outcomes) and (not OKAY in outcomes))
diff --git a/chromium/v8/tools/testrunner/local/testsuite.py b/chromium/v8/tools/testrunner/local/testsuite.py
index b0372e7f739..473e8b1efed 100644
--- a/chromium/v8/tools/testrunner/local/testsuite.py
+++ b/chromium/v8/tools/testrunner/local/testsuite.py
@@ -66,10 +66,7 @@ class TestSuite(object):
# Used in the status file and for stdout printing.
def CommonTestName(self, testcase):
- if utils.IsWindows():
- return testcase.path.replace("\\", "/")
- else:
- return testcase.path
+ return testcase.path
def ListTests(self, context):
raise NotImplementedError
@@ -87,36 +84,32 @@ class TestSuite(object):
def ReadTestCases(self, context):
self.tests = self.ListTests(context)
- @staticmethod
- def _FilterFlaky(flaky, mode):
- return (mode == "run" and not flaky) or (mode == "skip" and flaky)
-
- def FilterTestCasesByStatus(self, warn_unused_rules, flaky_tests="dontcare"):
+ def FilterTestCasesByStatus(self, warn_unused_rules):
filtered = []
used_rules = set()
for t in self.tests:
- flaky = False
testname = self.CommonTestName(t)
+ if utils.IsWindows():
+ testname = testname.replace("\\", "/")
if testname in self.rules:
used_rules.add(testname)
- # Even for skipped tests, as the TestCase object stays around and
- # PrintReport() uses it.
- t.outcomes = self.rules[testname]
- if statusfile.DoSkip(t.outcomes):
+ outcomes = self.rules[testname]
+ t.outcomes = outcomes # Even for skipped tests, as the TestCase
+ # object stays around and PrintReport() uses it.
+ if statusfile.DoSkip(outcomes):
continue # Don't add skipped tests to |filtered|.
- flaky = statusfile.IsFlaky(t.outcomes)
- skip = False
- for rule in self.wildcards:
- assert rule[-1] == '*'
- if testname.startswith(rule[:-1]):
- used_rules.add(rule)
- t.outcomes = self.wildcards[rule]
- if statusfile.DoSkip(t.outcomes):
- skip = True
- break # "for rule in self.wildcards"
- flaky = flaky or statusfile.IsFlaky(t.outcomes)
- if skip or self._FilterFlaky(flaky, flaky_tests):
- continue # "for t in self.tests"
+ if len(self.wildcards) != 0:
+ skip = False
+ for rule in self.wildcards:
+ assert rule[-1] == '*'
+ if testname.startswith(rule[:-1]):
+ used_rules.add(rule)
+ outcomes = self.wildcards[rule]
+ t.outcomes = outcomes
+ if statusfile.DoSkip(outcomes):
+ skip = True
+ break # "for rule in self.wildcards"
+ if skip: continue # "for t in self.tests"
filtered.append(t)
self.tests = filtered
diff --git a/chromium/v8/tools/testrunner/local/verbose.py b/chromium/v8/tools/testrunner/local/verbose.py
index 00c330d2d9c..f6934675231 100644
--- a/chromium/v8/tools/testrunner/local/verbose.py
+++ b/chromium/v8/tools/testrunner/local/verbose.py
@@ -54,7 +54,7 @@ def PrintReport(tests):
skipped += 1
continue
if statusfile.TIMEOUT in o: timeout += 1
- if statusfile.IsPassOrFail(o): nocrash += 1
+ if statusfile.IsFlaky(o): nocrash += 1
if list(o) == [statusfile.PASS]: passes += 1
if statusfile.IsFailOk(o): fail_ok += 1
if list(o) == [statusfile.FAIL]: fail += 1
diff --git a/chromium/v8/tools/tickprocessor.js b/chromium/v8/tools/tickprocessor.js
index f1a11ccc948..967bd3c5b71 100644
--- a/chromium/v8/tools/tickprocessor.js
+++ b/chromium/v8/tools/tickprocessor.js
@@ -249,8 +249,7 @@ TickProcessor.VmStates = {
GC: 1,
COMPILER: 2,
OTHER: 3,
- EXTERNAL: 4,
- IDLE: 5
+ EXTERNAL: 4
};
diff --git a/chromium/v8/tools/v8heapconst.py b/chromium/v8/tools/v8heapconst.py
deleted file mode 100644
index 57a1f595ace..00000000000
--- a/chromium/v8/tools/v8heapconst.py
+++ /dev/null
@@ -1,255 +0,0 @@
-# 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 file is automatically generated from the V8 source and should not
-# be modified manually, run 'make grokdump' instead to update this file.
-
-# List of known V8 instance types.
-INSTANCE_TYPES = {
- 64: "STRING_TYPE",
- 68: "ASCII_STRING_TYPE",
- 65: "CONS_STRING_TYPE",
- 69: "CONS_ASCII_STRING_TYPE",
- 67: "SLICED_STRING_TYPE",
- 71: "SLICED_ASCII_STRING_TYPE",
- 66: "EXTERNAL_STRING_TYPE",
- 70: "EXTERNAL_ASCII_STRING_TYPE",
- 74: "EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE",
- 82: "SHORT_EXTERNAL_STRING_TYPE",
- 86: "SHORT_EXTERNAL_ASCII_STRING_TYPE",
- 90: "SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE",
- 0: "INTERNALIZED_STRING_TYPE",
- 4: "ASCII_INTERNALIZED_STRING_TYPE",
- 1: "CONS_INTERNALIZED_STRING_TYPE",
- 5: "CONS_ASCII_INTERNALIZED_STRING_TYPE",
- 2: "EXTERNAL_INTERNALIZED_STRING_TYPE",
- 6: "EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE",
- 10: "EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE",
- 18: "SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE",
- 22: "SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE",
- 26: "SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE",
- 128: "SYMBOL_TYPE",
- 129: "MAP_TYPE",
- 130: "CODE_TYPE",
- 131: "ODDBALL_TYPE",
- 132: "CELL_TYPE",
- 133: "PROPERTY_CELL_TYPE",
- 134: "HEAP_NUMBER_TYPE",
- 135: "FOREIGN_TYPE",
- 136: "BYTE_ARRAY_TYPE",
- 137: "FREE_SPACE_TYPE",
- 138: "EXTERNAL_BYTE_ARRAY_TYPE",
- 139: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
- 140: "EXTERNAL_SHORT_ARRAY_TYPE",
- 141: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
- 142: "EXTERNAL_INT_ARRAY_TYPE",
- 143: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
- 144: "EXTERNAL_FLOAT_ARRAY_TYPE",
- 145: "EXTERNAL_DOUBLE_ARRAY_TYPE",
- 146: "EXTERNAL_PIXEL_ARRAY_TYPE",
- 148: "FILLER_TYPE",
- 149: "DECLARED_ACCESSOR_DESCRIPTOR_TYPE",
- 150: "DECLARED_ACCESSOR_INFO_TYPE",
- 151: "EXECUTABLE_ACCESSOR_INFO_TYPE",
- 152: "ACCESSOR_PAIR_TYPE",
- 153: "ACCESS_CHECK_INFO_TYPE",
- 154: "INTERCEPTOR_INFO_TYPE",
- 155: "CALL_HANDLER_INFO_TYPE",
- 156: "FUNCTION_TEMPLATE_INFO_TYPE",
- 157: "OBJECT_TEMPLATE_INFO_TYPE",
- 158: "SIGNATURE_INFO_TYPE",
- 159: "TYPE_SWITCH_INFO_TYPE",
- 161: "ALLOCATION_MEMENTO_TYPE",
- 160: "ALLOCATION_SITE_TYPE",
- 162: "SCRIPT_TYPE",
- 163: "CODE_CACHE_TYPE",
- 164: "POLYMORPHIC_CODE_CACHE_TYPE",
- 165: "TYPE_FEEDBACK_INFO_TYPE",
- 166: "ALIASED_ARGUMENTS_ENTRY_TYPE",
- 167: "BOX_TYPE",
- 170: "FIXED_ARRAY_TYPE",
- 147: "FIXED_DOUBLE_ARRAY_TYPE",
- 171: "SHARED_FUNCTION_INFO_TYPE",
- 172: "JS_MESSAGE_OBJECT_TYPE",
- 175: "JS_VALUE_TYPE",
- 176: "JS_DATE_TYPE",
- 177: "JS_OBJECT_TYPE",
- 178: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
- 179: "JS_GENERATOR_OBJECT_TYPE",
- 180: "JS_MODULE_TYPE",
- 181: "JS_GLOBAL_OBJECT_TYPE",
- 182: "JS_BUILTINS_OBJECT_TYPE",
- 183: "JS_GLOBAL_PROXY_TYPE",
- 184: "JS_ARRAY_TYPE",
- 185: "JS_ARRAY_BUFFER_TYPE",
- 186: "JS_TYPED_ARRAY_TYPE",
- 187: "JS_DATA_VIEW_TYPE",
- 174: "JS_PROXY_TYPE",
- 188: "JS_SET_TYPE",
- 189: "JS_MAP_TYPE",
- 190: "JS_WEAK_MAP_TYPE",
- 191: "JS_WEAK_SET_TYPE",
- 192: "JS_REGEXP_TYPE",
- 193: "JS_FUNCTION_TYPE",
- 173: "JS_FUNCTION_PROXY_TYPE",
- 168: "DEBUG_INFO_TYPE",
- 169: "BREAK_POINT_INFO_TYPE",
-}
-
-# List of known V8 maps.
-KNOWN_MAPS = {
- 0x08081: (136, "ByteArrayMap"),
- 0x080a9: (129, "MetaMap"),
- 0x080d1: (131, "OddballMap"),
- 0x080f9: (4, "AsciiInternalizedStringMap"),
- 0x08121: (170, "FixedArrayMap"),
- 0x08149: (134, "HeapNumberMap"),
- 0x08171: (137, "FreeSpaceMap"),
- 0x08199: (148, "OnePointerFillerMap"),
- 0x081c1: (148, "TwoPointerFillerMap"),
- 0x081e9: (132, "CellMap"),
- 0x08211: (133, "GlobalPropertyCellMap"),
- 0x08239: (171, "SharedFunctionInfoMap"),
- 0x08261: (170, "NativeContextMap"),
- 0x08289: (130, "CodeMap"),
- 0x082b1: (170, "ScopeInfoMap"),
- 0x082d9: (170, "FixedCOWArrayMap"),
- 0x08301: (147, "FixedDoubleArrayMap"),
- 0x08329: (170, "HashTableMap"),
- 0x08351: (128, "SymbolMap"),
- 0x08379: (64, "StringMap"),
- 0x083a1: (68, "AsciiStringMap"),
- 0x083c9: (65, "ConsStringMap"),
- 0x083f1: (69, "ConsAsciiStringMap"),
- 0x08419: (67, "SlicedStringMap"),
- 0x08441: (71, "SlicedAsciiStringMap"),
- 0x08469: (66, "ExternalStringMap"),
- 0x08491: (74, "ExternalStringWithOneByteDataMap"),
- 0x084b9: (70, "ExternalAsciiStringMap"),
- 0x084e1: (82, "ShortExternalStringMap"),
- 0x08509: (90, "ShortExternalStringWithOneByteDataMap"),
- 0x08531: (0, "InternalizedStringMap"),
- 0x08559: (1, "ConsInternalizedStringMap"),
- 0x08581: (5, "ConsAsciiInternalizedStringMap"),
- 0x085a9: (2, "ExternalInternalizedStringMap"),
- 0x085d1: (10, "ExternalInternalizedStringWithOneByteDataMap"),
- 0x085f9: (6, "ExternalAsciiInternalizedStringMap"),
- 0x08621: (18, "ShortExternalInternalizedStringMap"),
- 0x08649: (26, "ShortExternalInternalizedStringWithOneByteDataMap"),
- 0x08671: (22, "ShortExternalAsciiInternalizedStringMap"),
- 0x08699: (86, "ShortExternalAsciiStringMap"),
- 0x086c1: (64, "UndetectableStringMap"),
- 0x086e9: (68, "UndetectableAsciiStringMap"),
- 0x08711: (138, "ExternalByteArrayMap"),
- 0x08739: (139, "ExternalUnsignedByteArrayMap"),
- 0x08761: (140, "ExternalShortArrayMap"),
- 0x08789: (141, "ExternalUnsignedShortArrayMap"),
- 0x087b1: (142, "ExternalIntArrayMap"),
- 0x087d9: (143, "ExternalUnsignedIntArrayMap"),
- 0x08801: (144, "ExternalFloatArrayMap"),
- 0x08829: (145, "ExternalDoubleArrayMap"),
- 0x08851: (146, "ExternalPixelArrayMap"),
- 0x08879: (170, "NonStrictArgumentsElementsMap"),
- 0x088a1: (170, "FunctionContextMap"),
- 0x088c9: (170, "CatchContextMap"),
- 0x088f1: (170, "WithContextMap"),
- 0x08919: (170, "BlockContextMap"),
- 0x08941: (170, "ModuleContextMap"),
- 0x08969: (170, "GlobalContextMap"),
- 0x08991: (172, "JSMessageObjectMap"),
- 0x089b9: (135, "ForeignMap"),
- 0x089e1: (177, "NeanderMap"),
- 0x08a09: (161, "AllocationMementoMap"),
- 0x08a31: (160, "AllocationSiteMap"),
- 0x08a59: (164, "PolymorphicCodeCacheMap"),
- 0x08a81: (162, "ScriptMap"),
- 0x08ad1: (177, "ExternalMap"),
- 0x08af9: (167, "BoxMap"),
- 0x08b21: (149, "DeclaredAccessorDescriptorMap"),
- 0x08b49: (150, "DeclaredAccessorInfoMap"),
- 0x08b71: (151, "ExecutableAccessorInfoMap"),
- 0x08b99: (152, "AccessorPairMap"),
- 0x08bc1: (153, "AccessCheckInfoMap"),
- 0x08be9: (154, "InterceptorInfoMap"),
- 0x08c11: (155, "CallHandlerInfoMap"),
- 0x08c39: (156, "FunctionTemplateInfoMap"),
- 0x08c61: (157, "ObjectTemplateInfoMap"),
- 0x08c89: (158, "SignatureInfoMap"),
- 0x08cb1: (159, "TypeSwitchInfoMap"),
- 0x08cd9: (163, "CodeCacheMap"),
- 0x08d01: (165, "TypeFeedbackInfoMap"),
- 0x08d29: (166, "AliasedArgumentsEntryMap"),
- 0x08d51: (168, "DebugInfoMap"),
- 0x08d79: (169, "BreakPointInfoMap"),
-}
-
-# List of known V8 objects.
-KNOWN_OBJECTS = {
- ("OLD_POINTER_SPACE", 0x08081): "NullValue",
- ("OLD_POINTER_SPACE", 0x08091): "UndefinedValue",
- ("OLD_POINTER_SPACE", 0x080a1): "TheHoleValue",
- ("OLD_POINTER_SPACE", 0x080b1): "TrueValue",
- ("OLD_POINTER_SPACE", 0x080c1): "FalseValue",
- ("OLD_POINTER_SPACE", 0x080d1): "UninitializedValue",
- ("OLD_POINTER_SPACE", 0x080e1): "NoInterceptorResultSentinel",
- ("OLD_POINTER_SPACE", 0x080f1): "ArgumentsMarker",
- ("OLD_POINTER_SPACE", 0x08101): "NumberStringCache",
- ("OLD_POINTER_SPACE", 0x08909): "SingleCharacterStringCache",
- ("OLD_POINTER_SPACE", 0x08d11): "StringSplitCache",
- ("OLD_POINTER_SPACE", 0x09119): "RegExpMultipleCache",
- ("OLD_POINTER_SPACE", 0x09521): "TerminationException",
- ("OLD_POINTER_SPACE", 0x09531): "MessageListeners",
- ("OLD_POINTER_SPACE", 0x0954d): "CodeStubs",
- ("OLD_POINTER_SPACE", 0x0a9d9): "NonMonomorphicCache",
- ("OLD_POINTER_SPACE", 0x0afed): "PolymorphicCodeCache",
- ("OLD_POINTER_SPACE", 0x0aff5): "NativesSourceCache",
- ("OLD_POINTER_SPACE", 0x0b035): "EmptyScript",
- ("OLD_POINTER_SPACE", 0x0b06d): "IntrinsicFunctionNames",
- ("OLD_POINTER_SPACE", 0x0e089): "ObservationState",
- ("OLD_POINTER_SPACE", 0x0e095): "FrozenSymbol",
- ("OLD_POINTER_SPACE", 0x0e0a1): "ElementsTransitionSymbol",
- ("OLD_POINTER_SPACE", 0x0e0ad): "EmptySlowElementDictionary",
- ("OLD_POINTER_SPACE", 0x0e249): "ObservedSymbol",
- ("OLD_POINTER_SPACE", 0x274e9): "StringTable",
- ("OLD_DATA_SPACE", 0x08099): "EmptyDescriptorArray",
- ("OLD_DATA_SPACE", 0x080a1): "EmptyFixedArray",
- ("OLD_DATA_SPACE", 0x080a9): "NanValue",
- ("OLD_DATA_SPACE", 0x08141): "EmptyByteArray",
- ("OLD_DATA_SPACE", 0x08269): "EmptyExternalByteArray",
- ("OLD_DATA_SPACE", 0x08275): "EmptyExternalUnsignedByteArray",
- ("OLD_DATA_SPACE", 0x08281): "EmptyExternalShortArray",
- ("OLD_DATA_SPACE", 0x0828d): "EmptyExternalUnsignedShortArray",
- ("OLD_DATA_SPACE", 0x08299): "EmptyExternalIntArray",
- ("OLD_DATA_SPACE", 0x082a5): "EmptyExternalUnsignedIntArray",
- ("OLD_DATA_SPACE", 0x082b1): "EmptyExternalFloatArray",
- ("OLD_DATA_SPACE", 0x082bd): "EmptyExternalDoubleArray",
- ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
- ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
- ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
- ("CODE_SPACE", 0x10d01): "JsConstructEntryCode",
- ("CODE_SPACE", 0x183c1): "JsEntryCode",
-}
diff --git a/chromium/v8/tools/v8heapconst.py.tmpl b/chromium/v8/tools/v8heapconst.py.tmpl
deleted file mode 100644
index a773f47c8b9..00000000000
--- a/chromium/v8/tools/v8heapconst.py.tmpl
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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 file is automatically generated from the V8 source and should not
-# be modified manually, run 'make grokdump' instead to update this file.
-