v8: upgrade v8 to 3.20.14.1
authorBen Noordhuis <info@bnoordhuis.nl>
Sat, 10 Aug 2013 14:27:43 +0000 (16:27 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Sat, 10 Aug 2013 14:27:43 +0000 (16:27 +0200)
217 files changed:
deps/v8/.gitignore
deps/v8/AUTHORS
deps/v8/ChangeLog
deps/v8/DEPS
deps/v8/Makefile
deps/v8/PRESUBMIT.py
deps/v8/build/standalone.gypi
deps/v8/build/toolchain.gypi
deps/v8/include/v8-debug.h
deps/v8/include/v8-preparser.h
deps/v8/include/v8-profiler.h
deps/v8/include/v8-testing.h
deps/v8/include/v8.h
deps/v8/src/api.cc
deps/v8/src/arm/assembler-arm.cc
deps/v8/src/arm/assembler-arm.h
deps/v8/src/arm/builtins-arm.cc
deps/v8/src/arm/code-stubs-arm.cc
deps/v8/src/arm/codegen-arm.cc
deps/v8/src/arm/debug-arm.cc
deps/v8/src/arm/frames-arm.h
deps/v8/src/arm/full-codegen-arm.cc
deps/v8/src/arm/lithium-arm.cc
deps/v8/src/arm/lithium-arm.h
deps/v8/src/arm/lithium-codegen-arm.cc
deps/v8/src/arm/lithium-codegen-arm.h
deps/v8/src/arm/lithium-gap-resolver-arm.cc
deps/v8/src/arm/macro-assembler-arm.cc
deps/v8/src/arm/macro-assembler-arm.h
deps/v8/src/array-iterator.js
deps/v8/src/ast.cc
deps/v8/src/ast.h
deps/v8/src/atomicops_internals_tsan.h
deps/v8/src/bootstrapper.cc
deps/v8/src/builtins.h
deps/v8/src/checks.h
deps/v8/src/code-stubs-hydrogen.cc
deps/v8/src/code-stubs.cc
deps/v8/src/code-stubs.h
deps/v8/src/collection.js
deps/v8/src/compilation-cache.cc
deps/v8/src/compilation-cache.h
deps/v8/src/compiler.cc
deps/v8/src/compiler.h
deps/v8/src/d8.cc
deps/v8/src/d8.h
deps/v8/src/debug.cc
deps/v8/src/deoptimizer.cc
deps/v8/src/extensions/i18n/date-format.cc [deleted file]
deps/v8/src/extensions/i18n/date-format.js
deps/v8/src/extensions/i18n/footer.js
deps/v8/src/extensions/i18n/header.js
deps/v8/src/extensions/i18n/i18n-extension.cc
deps/v8/src/extensions/i18n/i18n-utils.cc
deps/v8/src/extensions/i18n/i18n-utils.js
deps/v8/src/extensions/i18n/locale.cc [deleted file]
deps/v8/src/extensions/i18n/locale.js
deps/v8/src/factory.cc
deps/v8/src/flag-definitions.h
deps/v8/src/frames.cc
deps/v8/src/frames.h
deps/v8/src/full-codegen.cc
deps/v8/src/full-codegen.h
deps/v8/src/global-handles.cc
deps/v8/src/global-handles.h
deps/v8/src/globals.h
deps/v8/src/harmony-array.js [new file with mode: 0644]
deps/v8/src/harmony-string.js [new file with mode: 0644]
deps/v8/src/heap-snapshot-generator.cc
deps/v8/src/heap-snapshot-generator.h
deps/v8/src/heap.cc
deps/v8/src/heap.h
deps/v8/src/hydrogen-bce.cc
deps/v8/src/hydrogen-bch.cc
deps/v8/src/hydrogen-dehoist.cc
deps/v8/src/hydrogen-instructions.cc
deps/v8/src/hydrogen-instructions.h
deps/v8/src/hydrogen-uint32-analysis.cc
deps/v8/src/hydrogen.cc
deps/v8/src/hydrogen.h
deps/v8/src/i18n.cc [new file with mode: 0644]
deps/v8/src/i18n.h [moved from deps/v8/src/extensions/i18n/date-format.h with 69% similarity]
deps/v8/src/ia32/assembler-ia32.cc
deps/v8/src/ia32/builtins-ia32.cc
deps/v8/src/ia32/code-stubs-ia32.cc
deps/v8/src/ia32/codegen-ia32.cc
deps/v8/src/ia32/debug-ia32.cc
deps/v8/src/ia32/deoptimizer-ia32.cc
deps/v8/src/ia32/frames-ia32.h
deps/v8/src/ia32/full-codegen-ia32.cc
deps/v8/src/ia32/ic-ia32.cc
deps/v8/src/ia32/lithium-codegen-ia32.cc
deps/v8/src/ia32/lithium-codegen-ia32.h
deps/v8/src/ia32/lithium-ia32.cc
deps/v8/src/ia32/lithium-ia32.h
deps/v8/src/ia32/macro-assembler-ia32.cc
deps/v8/src/ia32/macro-assembler-ia32.h
deps/v8/src/ia32/stub-cache-ia32.cc
deps/v8/src/ic.cc
deps/v8/src/ic.h
deps/v8/src/icu_util.cc
deps/v8/src/isolate.cc
deps/v8/src/isolate.h
deps/v8/src/lithium.cc
deps/v8/src/log.cc
deps/v8/src/mark-compact.cc
deps/v8/src/mark-compact.h
deps/v8/src/messages.js
deps/v8/src/mips/assembler-mips.h
deps/v8/src/mips/builtins-mips.cc
deps/v8/src/mips/code-stubs-mips.cc
deps/v8/src/mips/codegen-mips.cc
deps/v8/src/mips/debug-mips.cc
deps/v8/src/mips/frames-mips.h
deps/v8/src/mips/full-codegen-mips.cc
deps/v8/src/mips/lithium-codegen-mips.cc
deps/v8/src/mips/lithium-codegen-mips.h
deps/v8/src/mips/lithium-gap-resolver-mips.cc
deps/v8/src/mips/lithium-mips.cc
deps/v8/src/mips/lithium-mips.h
deps/v8/src/mips/macro-assembler-mips.cc
deps/v8/src/mips/macro-assembler-mips.h
deps/v8/src/object-observe.js
deps/v8/src/objects-debug.cc
deps/v8/src/objects-inl.h
deps/v8/src/objects-printer.cc
deps/v8/src/objects-visiting.h
deps/v8/src/objects.cc
deps/v8/src/objects.h
deps/v8/src/parser.cc
deps/v8/src/platform-linux.cc
deps/v8/src/profile-generator.cc
deps/v8/src/profile-generator.h
deps/v8/src/runtime.cc
deps/v8/src/runtime.h
deps/v8/src/runtime.js
deps/v8/src/sampler.cc
deps/v8/src/serialize.cc
deps/v8/src/spaces.h
deps/v8/src/transitions-inl.h
deps/v8/src/transitions.cc
deps/v8/src/transitions.h
deps/v8/src/type-info.cc
deps/v8/src/type-info.h
deps/v8/src/typedarray.js
deps/v8/src/typing.cc
deps/v8/src/v8.cc
deps/v8/src/version.cc
deps/v8/src/x64/assembler-x64-inl.h
deps/v8/src/x64/assembler-x64.cc
deps/v8/src/x64/assembler-x64.h
deps/v8/src/x64/builtins-x64.cc
deps/v8/src/x64/code-stubs-x64.cc
deps/v8/src/x64/codegen-x64.cc
deps/v8/src/x64/debug-x64.cc
deps/v8/src/x64/deoptimizer-x64.cc
deps/v8/src/x64/frames-x64.h
deps/v8/src/x64/full-codegen-x64.cc
deps/v8/src/x64/ic-x64.cc
deps/v8/src/x64/lithium-codegen-x64.cc
deps/v8/src/x64/lithium-codegen-x64.h
deps/v8/src/x64/lithium-x64.cc
deps/v8/src/x64/lithium-x64.h
deps/v8/src/x64/macro-assembler-x64.cc
deps/v8/src/x64/macro-assembler-x64.h
deps/v8/src/x64/regexp-macro-assembler-x64.cc
deps/v8/src/x64/stub-cache-x64.cc
deps/v8/src/zone.h
deps/v8/test/benchmarks/benchmarks.status [new file with mode: 0644]
deps/v8/test/benchmarks/testcfg.py [new file with mode: 0644]
deps/v8/test/cctest/cctest.cc
deps/v8/test/cctest/cctest.h
deps/v8/test/cctest/test-api.cc
deps/v8/test/cctest/test-assembler-arm.cc
deps/v8/test/cctest/test-code-stubs-ia32.cc
deps/v8/test/cctest/test-code-stubs-x64.cc
deps/v8/test/cctest/test-compiler.cc
deps/v8/test/cctest/test-cpu-profiler.cc
deps/v8/test/cctest/test-global-handles.cc
deps/v8/test/cctest/test-heap.cc
deps/v8/test/cctest/test-strings.cc
deps/v8/test/intl/break-iterator/default-locale.js
deps/v8/test/intl/break-iterator/wellformed-unsupported-locale.js
deps/v8/test/intl/collator/default-locale.js
deps/v8/test/intl/collator/wellformed-unsupported-locale.js
deps/v8/test/intl/date-format/default-locale.js
deps/v8/test/intl/date-format/wellformed-unsupported-locale.js
deps/v8/test/intl/intl.status
deps/v8/test/intl/number-format/default-locale.js
deps/v8/test/intl/number-format/wellformed-unsupported-locale.js
deps/v8/test/intl/testcfg.py
deps/v8/test/mjsunit/harmony/array-find.js [new file with mode: 0644]
deps/v8/test/mjsunit/harmony/array-findindex.js [new file with mode: 0644]
deps/v8/test/mjsunit/harmony/array-iterator.js
deps/v8/test/mjsunit/harmony/collections.js
deps/v8/test/mjsunit/harmony/object-observe.js
deps/v8/test/mjsunit/harmony/proxies-example-membrane.js
deps/v8/test/mjsunit/harmony/proxies-hash.js
deps/v8/test/mjsunit/harmony/string-contains.js [new file with mode: 0644]
deps/v8/test/mjsunit/harmony/string-endswith.js [new file with mode: 0644]
deps/v8/test/mjsunit/harmony/string-repeat.js [new file with mode: 0644]
deps/v8/test/mjsunit/harmony/string-startswith.js [new file with mode: 0644]
deps/v8/test/mjsunit/math-abs.js
deps/v8/test/mjsunit/regress/regress-264203.js [moved from deps/v8/test/intl/general/v8Intl-exists.js with 83% similarity]
deps/v8/test/mjsunit/regress/regress-2813.js [new file with mode: 0644]
deps/v8/test/mjsunit/regress/regress-omit-checks.js [new file with mode: 0644]
deps/v8/test/mjsunit/unary-minus-deopt.js [moved from deps/v8/src/extensions/i18n/locale.h with 60% similarity]
deps/v8/test/webkit/webkit.status
deps/v8/tools/grokdump.py
deps/v8/tools/gyp/v8.gyp
deps/v8/tools/run-tests.py
deps/v8/tools/testrunner/local/old_statusfile.py
deps/v8/tools/testrunner/local/statusfile.py
deps/v8/tools/testrunner/local/testsuite.py
deps/v8/tools/testrunner/local/verbose.py
deps/v8/tools/v8heapconst.py [new file with mode: 0644]
deps/v8/tools/v8heapconst.py.tmpl [new file with mode: 0644]

index 2f524be..282e463 100644 (file)
@@ -27,12 +27,22 @@ d8
 d8_g
 shell
 shell_g
+/_*
 /build/Debug
 /build/gyp
 /build/ipch/
 /build/Release
+/hydrogen.cfg
 /obj
 /out
+/perf.data
+/perf.data.old
+/test/benchmarks/benchmarks.status2
+/test/benchmarks/CHECKED_OUT_*
+/test/benchmarks/downloaded_*
+/test/benchmarks/kraken
+/test/benchmarks/octane
+/test/benchmarks/sunspider
 /test/cctest/cctest.status2
 /test/message/message.status2
 /test/mjsunit/mjsunit.status2
@@ -52,6 +62,7 @@ shell_g
 /tools/oom_dump/oom_dump.o
 /tools/visual_studio/Debug
 /tools/visual_studio/Release
+/v8.log.ll
 /xcodebuild
 TAGS
 *.Makefile
@@ -59,4 +70,3 @@ GTAGS
 GRTAGS
 GSYMS
 GPATH
-/_*
index 1a927c4..46e3a14 100644 (file)
@@ -10,6 +10,7 @@ Hewlett-Packard Development Company, LP
 Igalia, S.L.
 Joyent, Inc.
 Bloomberg Finance L.P.
+NVIDIA Corporation
 
 Akinori MUSHA <knu@FreeBSD.org>
 Alexander Botero-Lowry <alexbl@FreeBSD.org>
index 567afd2..b19fda2 100644 (file)
@@ -1,3 +1,44 @@
+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)
+
+        Calling Map etc without new should throw TypeError (issue 2819)
+
+        Fixed a crash for large code objects on ARM (Chromium issue 2736)
+
+        Fixed stale unhandlified value in JSObject::SetPropertyForResult.
+        (Chromium issue 265894)
+
+        Added new Harmony methods to String.prototype object.
+        (issue 2796,v8:2797,v8:2798,v8:2799)
+
+        Performance and stability improvements on all platforms.
+
+
 2013-07-30: Version 3.20.11
 
         Performance and stability improvements on all platforms.
index da87853..b91ae4e 100644 (file)
@@ -5,10 +5,10 @@
 deps = {
   # Remember to keep the revision in sync with the Makefile.
   "v8/build/gyp":
-    "http://gyp.googlecode.com/svn/trunk@1656",
+    "http://gyp.googlecode.com/svn/trunk@1685",
 
   "v8/third_party/icu":
-    "https://src.chromium.org/chrome/trunk/deps/third_party/icu46@213354",
+    "https://src.chromium.org/chrome/trunk/deps/third_party/icu46@214189",
 }
 
 deps_os = {
index a749fd0..288c257 100644 (file)
@@ -192,6 +192,7 @@ 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"
@@ -392,7 +393,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
 
@@ -401,11 +402,17 @@ $(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:
        svn checkout --force http://gyp.googlecode.com/svn/trunk build/gyp \
-           --revision 1656
+           --revision 1685
        svn checkout --force \
            https://src.chromium.org/chrome/trunk/deps/third_party/icu46 \
-           third_party/icu --revision 213354
+           third_party/icu --revision 214189
index 1f176e0..819331f 100644 (file)
@@ -69,4 +69,7 @@ def CheckChangeOnCommit(input_api, output_api):
   results.extend(_CommonChecks(input_api, output_api))
   results.extend(input_api.canned_checks.CheckChangeHasDescription(
       input_api, output_api))
+  results.extend(input_api.canned_checks.CheckTreeIsOpen(
+      input_api, output_api,
+      json_url='http://v8-status.appspot.com/current?format=json'))
   return results
index ab2dfd5..5c017d5 100644 (file)
     },
     'target_conditions': [
       ['v8_code == 0', {
+        'defines!': [
+          'DEBUG',
+        ],
         'conditions': [
           ['os_posix == 1 and OS != "mac"', {
             'cflags!': [
             },
           }],
           ['OS == "win"', {
-            'defines!': [
-              'DEBUG',
-            ],
             'msvs_settings': {
               'VCCLCompilerTool': {
                 'WarnAsError': 'false',
index 36d60c2..ddb8aaf 100644 (file)
     'v8_enable_backtrace%': 0,
 
     # Speeds up Debug builds:
-    # 0 - compiler optimizations off (debuggable) (default). This may
+    # 0 - Compiler optimizations off (debuggable) (default). This may
     #     be 5x slower than Release (or worse).
-    # 1 - turn on compiler optimizations. and #undef DEBUG/#define NDEBUG.
-    #     This may be hard or impossible to debug. This may still be
-    #     2x slower than Release (or worse).
+    # 1 - Turn on compiler optimizations. This may be hard or impossible to
+    #     debug. This may still be 2x slower than Release (or worse).
     # 2 - Turn on optimizations, and also #undef DEBUG / #define NDEBUG
     #     (but leave V8_ENABLE_CHECKS and most other assertions enabled.
     #     This may cause some v8 tests to fail in the Debug configuration.
         'msvs_settings': {
           'VCCLCompilerTool': {
             'conditions': [
-              ['component=="shared_library"', {
-                'RuntimeLibrary': '3',  # /MDd
-              }, {
-                'RuntimeLibrary': '1',  # /MTd
-              }],
               ['v8_optimized_debug==0', {
                 'Optimization': '0',
-              }, {
+                'conditions': [
+                  ['component=="shared_library"', {
+                    'RuntimeLibrary': '3',  # /MDd
+                  }, {
+                    'RuntimeLibrary': '1',  # /MTd
+                  }],
+                ],
+              }],
+              ['v8_optimized_debug==1', {
+                'Optimization': '1',
+                'InlineFunctionExpansion': '2',
+                'EnableIntrinsicFunctions': 'true',
+                'FavorSizeOrSpeed': '0',
+                'StringPooling': 'true',
+                'BasicRuntimeChecks': '0',
+                'conditions': [
+                  ['component=="shared_library"', {
+                    'RuntimeLibrary': '3',  # /MDd
+                  }, {
+                    'RuntimeLibrary': '1',  # /MTd
+                  }],
+                ],
+              }],
+              ['v8_optimized_debug==2', {
                 'Optimization': '2',
                 'InlineFunctionExpansion': '2',
                 'EnableIntrinsicFunctions': 'true',
                 'BasicRuntimeChecks': '0',
                 'conditions': [
                   ['component=="shared_library"', {
-                    'RuntimeLibrary': '2',  #/MD
+                    'RuntimeLibrary': '3',  #/MDd
                   }, {
-                    'RuntimeLibrary': '0',  #/MT
+                    'RuntimeLibrary': '1',  #/MTd
                   }],
                   ['v8_target_arch=="x64"', {
                     # TODO(2207): remove this option once the bug is fixed.
             'conditions': [
               ['v8_optimized_debug==0', {
                 'LinkIncremental': '2',
-              }, {
+              }],
+              ['v8_optimized_debug==1', {
+                'LinkIncremental': '2',
+              }],
+              ['v8_optimized_debug==2', {
                 'LinkIncremental': '1',
                 'OptimizeReferences': '2',
                 'EnableCOMDATFolding': '2',
index e488aaa..bacccb6 100755 (executable)
 
 #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.
  */
@@ -81,7 +47,7 @@ enum DebugEvent {
 };
 
 
-class EXPORT Debug {
+class V8_EXPORT Debug {
  public:
   /**
    * A client object passed to the v8 debugger whose ownership will be taken by
index 3e39823..1da7718 100644 (file)
 #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 V8EXPORT PreParserData {
+class V8_EXPORT PreParserData {
  public:
   PreParserData(size_t size, const uint8_t* data)
       : data_(data), size_(size) { }
@@ -94,7 +60,7 @@ class V8EXPORT PreParserData {
 
 
 // Interface for a stream of Unicode characters.
-class V8EXPORT UnicodeInputStream {  // NOLINT - Thinks V8EXPORT is class name.
+class V8_EXPORT UnicodeInputStream {  // NOLINT - V8_EXPORT is not a class name.
  public:
   virtual ~UnicodeInputStream();
 
@@ -110,11 +76,9 @@ class V8EXPORT UnicodeInputStream {  // NOLINT - Thinks V8EXPORT is 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 V8EXPORT Preparse(UnicodeInputStream* input,
+PreParserData V8_EXPORT Preparse(UnicodeInputStream* input,
                                 size_t max_stack_size);
 
 }  // namespace v8.
 
-#undef V8EXPORT
-
 #endif  // PREPARSER_H
index cf28341..1d7b70d 100644 (file)
 
 #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.
  */
@@ -70,7 +40,7 @@ typedef uint32_t SnapshotObjectId;
 /**
  * CpuProfileNode represents a node in a call graph.
  */
-class V8EXPORT CpuProfileNode {
+class V8_EXPORT CpuProfileNode {
  public:
   /** Returns function name (empty string for anonymous functions.) */
   Handle<String> GetFunctionName() const;
@@ -125,7 +95,7 @@ class V8EXPORT 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 V8EXPORT CpuProfile {
+class V8_EXPORT CpuProfile {
  public:
   /** Returns CPU profile UID (assigned by the profiler.) */
   unsigned GetUid() const;
@@ -149,6 +119,18 @@ class V8EXPORT CpuProfile {
   const CpuProfileNode* GetSample(int index) const;
 
   /**
+    * Returns time when the profile recording started (in microseconds
+    * since the Epoch).
+    */
+  int64_t GetStartTime() const;
+
+  /**
+    * Returns time when the profile recording was stopped (in microseconds
+    * since the Epoch).
+    */
+  int64_t GetEndTime() const;
+
+  /**
    * Deletes the profile and removes it from CpuProfiler's list.
    * All pointers to nodes previously returned become invalid.
    * Profiles with the same uid but obtained using different
@@ -164,7 +146,7 @@ class V8EXPORT CpuProfile {
  * Interface for controlling CPU profiling. Instance of the
  * profiler can be retrieved using v8::Isolate::GetCpuProfiler.
  */
-class V8EXPORT CpuProfiler {
+class V8_EXPORT CpuProfiler {
  public:
   /**
    * A note on security tokens usage. As scripts from different
@@ -225,7 +207,7 @@ class HeapGraphNode;
  * HeapSnapshotEdge represents a directed connection between heap
  * graph nodes: from retainers to retained nodes.
  */
-class V8EXPORT HeapGraphEdge {
+class V8_EXPORT HeapGraphEdge {
  public:
   enum Type {
     kContextVariable = 0,  // A variable from a function context.
@@ -261,7 +243,7 @@ class V8EXPORT HeapGraphEdge {
 /**
  * HeapGraphNode represents a node in a heap graph.
  */
-class V8EXPORT HeapGraphNode {
+class V8_EXPORT HeapGraphNode {
  public:
   enum Type {
     kHidden = 0,      // Hidden node, may be filtered when shown to user.
@@ -313,7 +295,7 @@ class V8EXPORT HeapGraphNode {
 /**
  * HeapSnapshots record the state of the JS heap at some moment.
  */
-class V8EXPORT HeapSnapshot {
+class V8_EXPORT HeapSnapshot {
  public:
   enum SerializationFormat {
     kJSON = 0  // See format description near 'Serialize' method.
@@ -383,7 +365,7 @@ class RetainedObjectInfo;
  * Interface for controlling heap profiling. Instance of the
  * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
  */
-class V8EXPORT HeapProfiler {
+class V8_EXPORT HeapProfiler {
  public:
   /**
    * Callback function invoked for obtaining RetainedObjectInfo for
@@ -521,7 +503,7 @@ class V8EXPORT HeapProfiler {
  * keeps them alive only during snapshot collection. Afterwards, they
  * are freed by calling the Dispose class function.
  */
-class V8EXPORT RetainedObjectInfo {  // NOLINT
+class V8_EXPORT RetainedObjectInfo {  // NOLINT
  public:
   /** Called by V8 when it no longer needs an instance. */
   virtual void Dispose() = 0;
@@ -587,7 +569,4 @@ struct HeapStatsUpdate {
 }  // namespace v8
 
 
-#undef V8EXPORT
-
-
 #endif  // V8_V8_PROFILER_H_
index 59eebf9..97b467a 100644 (file)
 
 #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 V8EXPORT Testing {
+class V8_EXPORT Testing {
  public:
   enum StressType {
     kStressTypeOpt,
@@ -99,7 +69,7 @@ class V8EXPORT Testing {
 }  // namespace v8
 
 
-#undef V8EXPORT
+#undef V8_EXPORT
 
 
 #endif  // V8_V8_TEST_H_
index eb166ab..4b31e87 100644 (file)
@@ -40,6 +40,9 @@
 
 #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
 #endif
 
 #ifdef BUILDING_V8_SHARED
-#define V8EXPORT __declspec(dllexport)
+#define V8_EXPORT __declspec(dllexport)
 #elif USING_V8_SHARED
-#define V8EXPORT __declspec(dllimport)
+#define V8_EXPORT __declspec(dllimport)
 #else
-#define V8EXPORT
+#define V8_EXPORT
 #endif  // BUILDING_V8_SHARED
 
 #else  // _WIN32
 #if defined(__GNUC__) && ((__GNUC__ >= 4) || \
     (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(V8_SHARED)
 #ifdef BUILDING_V8_SHARED
-#define V8EXPORT __attribute__ ((visibility("default")))
+#define V8_EXPORT __attribute__ ((visibility("default")))
 #else
-#define V8EXPORT
+#define V8_EXPORT
 #endif
 #else
-#define V8EXPORT
+#define V8_EXPORT
 #endif
 
 #endif  // _WIN32
@@ -385,6 +388,11 @@ 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
@@ -430,6 +438,11 @@ 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
@@ -801,7 +814,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 V8EXPORT HandleScope {
+class V8_EXPORT HandleScope {
  public:
   // TODO(svenpanne) Deprecate me when Chrome is fixed!
   HandleScope();
@@ -840,7 +853,7 @@ class V8EXPORT HandleScope {
 
   // This Data class is accessible internally as HandleScopeData through a
   // typedef in the ImplementationUtilities class.
-  class V8EXPORT Data {
+  class V8_EXPORT Data {
    public:
     internal::Object** next;
     internal::Object** limit;
@@ -873,7 +886,7 @@ class V8EXPORT HandleScope {
 /**
  * The superclass of values and API object templates.
  */
-class V8EXPORT Data {
+class V8_EXPORT Data {
  private:
   Data();
 };
@@ -885,7 +898,7 @@ class V8EXPORT Data {
  * compiling it, and can be stored between compilations.  When script
  * data is given to the compile method compilation will be faster.
  */
-class V8EXPORT ScriptData {  // NOLINT
+class V8_EXPORT ScriptData {  // NOLINT
  public:
   virtual ~ScriptData() { }
 
@@ -942,24 +955,28 @@ class ScriptOrigin {
   V8_INLINE(ScriptOrigin(
       Handle<Value> resource_name,
       Handle<Integer> resource_line_offset = Handle<Integer>(),
-      Handle<Integer> resource_column_offset = Handle<Integer>()))
+      Handle<Integer> resource_column_offset = Handle<Integer>(),
+      Handle<Boolean> resource_is_shared_cross_origin = Handle<Boolean>()))
       : resource_name_(resource_name),
         resource_line_offset_(resource_line_offset),
-        resource_column_offset_(resource_column_offset) { }
+        resource_column_offset_(resource_column_offset),
+        resource_is_shared_cross_origin_(resource_is_shared_cross_origin) { }
   V8_INLINE(Handle<Value> ResourceName() const);
   V8_INLINE(Handle<Integer> ResourceLineOffset() const);
   V8_INLINE(Handle<Integer> ResourceColumnOffset() const);
+  V8_INLINE(Handle<Boolean> ResourceIsSharedCrossOrigin() const);
  private:
   Handle<Value> resource_name_;
   Handle<Integer> resource_line_offset_;
   Handle<Integer> resource_column_offset_;
+  Handle<Boolean> resource_is_shared_cross_origin_;
 };
 
 
 /**
  * A compiled JavaScript script.
  */
-class V8EXPORT Script {
+class V8_EXPORT Script {
  public:
   /**
    * Compiles the specified script (context-independent).
@@ -1077,7 +1094,7 @@ class V8EXPORT Script {
 /**
  * An error message.
  */
-class V8EXPORT Message {
+class V8_EXPORT Message {
  public:
   Local<String> Get() const;
   Local<String> GetSourceLine() const;
@@ -1130,6 +1147,12 @@ class V8EXPORT Message {
    */
   int GetEndColumn() const;
 
+  /**
+   * Passes on the value set by the embedder when it fed the script from which
+   * this Message was generated to V8.
+   */
+  bool IsSharedCrossOrigin() const;
+
   // TODO(1245381): Print to a string instead of on a FILE.
   static void PrintCurrentStackTrace(FILE* out);
 
@@ -1143,7 +1166,7 @@ class V8EXPORT Message {
  * snapshot of the execution stack and the information remains valid after
  * execution continues.
  */
-class V8EXPORT StackTrace {
+class V8_EXPORT StackTrace {
  public:
   /**
    * Flags that determine what information is placed captured for each
@@ -1192,7 +1215,7 @@ class V8EXPORT StackTrace {
 /**
  * A single JavaScript stack frame.
  */
-class V8EXPORT StackFrame {
+class V8_EXPORT StackFrame {
  public:
   /**
    * Returns the number, 1-based, of the line for the associate function call.
@@ -1244,13 +1267,29 @@ class V8EXPORT StackFrame {
 };
 
 
+/**
+ * A JSON Parser.
+ */
+class V8_EXPORT JSON {
+ public:
+  /**
+   * Tries to parse the string |json_string| and returns it as object if
+   * successful.
+   *
+   * \param json_string The string to parse.
+   * \return The corresponding object if successfully parsed.
+   */
+  static Local<Object> Parse(Local<String> json_string);
+};
+
+
 // --- Value ---
 
 
 /**
  * The superclass of all JavaScript values and objects.
  */
-class V8EXPORT Value : public Data {
+class V8_EXPORT Value : public Data {
  public:
   /**
    * Returns true if this value is the undefined value.  See ECMA-262
@@ -1481,14 +1520,14 @@ class V8EXPORT Value : public Data {
 /**
  * The superclass of primitive values.  See ECMA-262 4.3.2.
  */
-class V8EXPORT Primitive : public Value { };
+class V8_EXPORT Primitive : public Value { };
 
 
 /**
  * A primitive boolean value (ECMA-262, 4.3.14).  Either the true
  * or false value.
  */
-class V8EXPORT Boolean : public Primitive {
+class V8_EXPORT Boolean : public Primitive {
  public:
   bool Value() const;
   V8_INLINE(static Handle<Boolean> New(bool value));
@@ -1498,7 +1537,7 @@ class V8EXPORT Boolean : public Primitive {
 /**
  * A JavaScript string value (ECMA-262, 4.3.17).
  */
-class V8EXPORT String : public Primitive {
+class V8_EXPORT String : public Primitive {
  public:
   enum Encoding {
     UNKNOWN_ENCODING = 0x1,
@@ -1604,7 +1643,7 @@ class V8EXPORT String : public Primitive {
    */
   bool IsExternalAscii() const;
 
-  class V8EXPORT ExternalStringResourceBase {  // NOLINT
+  class V8_EXPORT ExternalStringResourceBase {  // NOLINT
    public:
     virtual ~ExternalStringResourceBase() {}
 
@@ -1633,7 +1672,7 @@ class V8EXPORT String : public Primitive {
    * ExternalStringResource to manage the life cycle of the underlying
    * buffer.  Note that the string data must be immutable.
    */
-  class V8EXPORT ExternalStringResource
+  class V8_EXPORT ExternalStringResource
       : public ExternalStringResourceBase {
    public:
     /**
@@ -1667,7 +1706,7 @@ class V8EXPORT String : public Primitive {
    * Use String::New or convert to 16 bit data for non-ASCII.
    */
 
-  class V8EXPORT ExternalAsciiStringResource
+  class V8_EXPORT ExternalAsciiStringResource
       : public ExternalStringResourceBase {
    public:
     /**
@@ -1820,7 +1859,7 @@ class V8EXPORT String : public Primitive {
    * then the length() method returns 0 and the * operator returns
    * NULL.
    */
-  class V8EXPORT Utf8Value {
+  class V8_EXPORT Utf8Value {
    public:
     explicit Utf8Value(Handle<v8::Value> obj);
     ~Utf8Value();
@@ -1843,7 +1882,7 @@ class V8EXPORT String : public Primitive {
    * method of the object) then the length() method returns 0 and the * operator
    * returns NULL.
    */
-  class V8EXPORT AsciiValue {
+  class V8_EXPORT AsciiValue {
    public:
     // TODO(dcarney): deprecate
     explicit AsciiValue(Handle<v8::Value> obj);
@@ -1866,7 +1905,7 @@ class V8EXPORT String : public Primitive {
    * method of the object) then the length() method returns 0 and the * operator
    * returns NULL.
    */
-  class V8EXPORT Value {
+  class V8_EXPORT Value {
    public:
     explicit Value(Handle<v8::Value> obj);
     ~Value();
@@ -1895,7 +1934,7 @@ class V8EXPORT String : public Primitive {
  *
  * This is an experimental feature. Use at your own risk.
  */
-class V8EXPORT Symbol : public Primitive {
+class V8_EXPORT Symbol : public Primitive {
  public:
   // Returns the print name string of the symbol, or undefined if none.
   Local<Value> Name() const;
@@ -1916,7 +1955,7 @@ class V8EXPORT Symbol : public Primitive {
 /**
  * A JavaScript number value (ECMA-262, 4.3.20)
  */
-class V8EXPORT Number : public Primitive {
+class V8_EXPORT Number : public Primitive {
  public:
   double Value() const;
   static Local<Number> New(double value);
@@ -1931,7 +1970,7 @@ class V8EXPORT Number : public Primitive {
 /**
  * A JavaScript value representing a signed integer.
  */
-class V8EXPORT Integer : public Number {
+class V8_EXPORT Integer : public Number {
  public:
   static Local<Integer> New(int32_t value);
   static Local<Integer> NewFromUnsigned(uint32_t value);
@@ -1948,7 +1987,7 @@ class V8EXPORT Integer : public Number {
 /**
  * A JavaScript value representing a 32-bit signed integer.
  */
-class V8EXPORT Int32 : public Integer {
+class V8_EXPORT Int32 : public Integer {
  public:
   int32_t Value() const;
  private:
@@ -1959,7 +1998,7 @@ class V8EXPORT Int32 : public Integer {
 /**
  * A JavaScript value representing a 32-bit unsigned integer.
  */
-class V8EXPORT Uint32 : public Integer {
+class V8_EXPORT Uint32 : public Integer {
  public:
   uint32_t Value() const;
  private:
@@ -2031,7 +2070,7 @@ enum AccessControl {
 /**
  * A JavaScript object (ECMA-262, 4.3.3)
  */
-class V8EXPORT Object : public Value {
+class V8_EXPORT Object : public Value {
  public:
   bool Set(Handle<Value> key,
            Handle<Value> value,
@@ -2303,7 +2342,7 @@ class V8EXPORT Object : public Value {
 /**
  * An instance of the built-in array constructor (ECMA-262, 15.4.2).
  */
-class V8EXPORT Array : public Object {
+class V8_EXPORT Array : public Object {
  public:
   uint32_t Length() const;
 
@@ -2329,7 +2368,7 @@ class V8EXPORT Array : public Object {
 /**
  * A JavaScript function object (ECMA-262, 15.3).
  */
-class V8EXPORT Function : public Object {
+class V8_EXPORT Function : public Object {
  public:
   Local<Object> NewInstance() const;
   Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
@@ -2385,7 +2424,7 @@ class V8EXPORT 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 V8EXPORT ArrayBuffer : public Object {
+class V8_EXPORT ArrayBuffer : public Object {
  public:
   /**
    * Allocator that V8 uses to allocate |ArrayBuffer|'s memory.
@@ -2394,19 +2433,41 @@ class V8EXPORT ArrayBuffer : public Object {
    *
    * This API is experimental and may change significantly.
    */
-  class V8EXPORT Allocator { // NOLINT
+  class V8_EXPORT Allocator { // NOLINT
    public:
     virtual ~Allocator() {}
 
     /**
      * Allocate |length| bytes. Return NULL if allocation is not successful.
+     * Memory should be initialized to zeroes.
      */
     virtual void* Allocate(size_t length) = 0;
+
     /**
-     * Free the memory pointed to |data|. That memory is guaranteed to be
-     * previously allocated by |Allocate|.
+     * Allocate |length| bytes. Return NULL if allocation is not successful.
+     * Memory does not have to be initialized.
      */
-    virtual void Free(void* data) = 0;
+    virtual void* AllocateUninitialized(size_t length) {
+      // Override with call to |Allocate| for compatibility
+      // with legacy version.
+      return Allocate(length);
+    }
+
+    /**
+     * Free the memory block of size |length|, pointed to by |data|.
+     * That memory is guaranteed to be previously allocated by |Allocate|.
+     */
+    virtual void Free(void* data, size_t length) {
+      // Override with call to |Free(void*)| for compatibility
+      // with legacy version.
+      Free(data);
+    }
+
+    /**
+     * Deprecated. Never called directly by V8.
+     * For compatibility with legacy version of this interface.
+     */
+    virtual void Free(void* data);
   };
 
   /**
@@ -2419,7 +2480,7 @@ class V8EXPORT ArrayBuffer : public Object {
    *
    * This API is experimental and may change significantly.
    */
-  class V8EXPORT Contents { // NOLINT
+  class V8_EXPORT Contents { // NOLINT
    public:
     Contents() : data_(NULL), byte_length_(0) {}
 
@@ -2502,7 +2563,7 @@ class V8EXPORT ArrayBuffer : public Object {
  *
  * This API is experimental and may change significantly.
  */
-class V8EXPORT ArrayBufferView : public Object {
+class V8_EXPORT ArrayBufferView : public Object {
  public:
   /**
    * Returns underlying ArrayBuffer.
@@ -2537,7 +2598,7 @@ class V8EXPORT ArrayBufferView : public Object {
  * (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT TypedArray : public ArrayBufferView {
+class V8_EXPORT TypedArray : public ArrayBufferView {
  public:
   /**
    * Number of elements in this typed array
@@ -2557,7 +2618,7 @@ class V8EXPORT TypedArray : public ArrayBufferView {
  * An instance of Uint8Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Uint8Array : public TypedArray {
+class V8_EXPORT Uint8Array : public TypedArray {
  public:
   static Local<Uint8Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2573,7 +2634,7 @@ class V8EXPORT Uint8Array : public TypedArray {
  * An instance of Uint8ClampedArray constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Uint8ClampedArray : public TypedArray {
+class V8_EXPORT Uint8ClampedArray : public TypedArray {
  public:
   static Local<Uint8ClampedArray> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2588,7 +2649,7 @@ class V8EXPORT Uint8ClampedArray : public TypedArray {
  * An instance of Int8Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Int8Array : public TypedArray {
+class V8_EXPORT Int8Array : public TypedArray {
  public:
   static Local<Int8Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2604,7 +2665,7 @@ class V8EXPORT Int8Array : public TypedArray {
  * An instance of Uint16Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Uint16Array : public TypedArray {
+class V8_EXPORT Uint16Array : public TypedArray {
  public:
   static Local<Uint16Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2620,7 +2681,7 @@ class V8EXPORT Uint16Array : public TypedArray {
  * An instance of Int16Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Int16Array : public TypedArray {
+class V8_EXPORT Int16Array : public TypedArray {
  public:
   static Local<Int16Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2636,7 +2697,7 @@ class V8EXPORT Int16Array : public TypedArray {
  * An instance of Uint32Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Uint32Array : public TypedArray {
+class V8_EXPORT Uint32Array : public TypedArray {
  public:
   static Local<Uint32Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2652,7 +2713,7 @@ class V8EXPORT Uint32Array : public TypedArray {
  * An instance of Int32Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Int32Array : public TypedArray {
+class V8_EXPORT Int32Array : public TypedArray {
  public:
   static Local<Int32Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2668,7 +2729,7 @@ class V8EXPORT Int32Array : public TypedArray {
  * An instance of Float32Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Float32Array : public TypedArray {
+class V8_EXPORT Float32Array : public TypedArray {
  public:
   static Local<Float32Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2684,7 +2745,7 @@ class V8EXPORT Float32Array : public TypedArray {
  * An instance of Float64Array constructor (ES6 draft 15.13.6).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT Float64Array : public TypedArray {
+class V8_EXPORT Float64Array : public TypedArray {
  public:
   static Local<Float64Array> New(Handle<ArrayBuffer> array_buffer,
                                size_t byte_offset, size_t length);
@@ -2700,7 +2761,7 @@ class V8EXPORT Float64Array : public TypedArray {
  * An instance of DataView constructor (ES6 draft 15.13.7).
  * This API is experimental and may change significantly.
  */
-class V8EXPORT DataView : public ArrayBufferView {
+class V8_EXPORT DataView : public ArrayBufferView {
  public:
   static Local<DataView> New(Handle<ArrayBuffer> array_buffer,
                              size_t byte_offset, size_t length);
@@ -2715,7 +2776,7 @@ class V8EXPORT DataView : public ArrayBufferView {
 /**
  * An instance of the built-in Date constructor (ECMA-262, 15.9).
  */
-class V8EXPORT Date : public Object {
+class V8_EXPORT Date : public Object {
  public:
   static Local<Value> New(double time);
 
@@ -2753,7 +2814,7 @@ class V8EXPORT Date : public Object {
 /**
  * A Number object (ECMA-262, 4.3.21).
  */
-class V8EXPORT NumberObject : public Object {
+class V8_EXPORT NumberObject : public Object {
  public:
   static Local<Value> New(double value);
 
@@ -2776,7 +2837,7 @@ class V8EXPORT NumberObject : public Object {
 /**
  * A Boolean object (ECMA-262, 4.3.15).
  */
-class V8EXPORT BooleanObject : public Object {
+class V8_EXPORT BooleanObject : public Object {
  public:
   static Local<Value> New(bool value);
 
@@ -2799,7 +2860,7 @@ class V8EXPORT BooleanObject : public Object {
 /**
  * A String object (ECMA-262, 4.3.18).
  */
-class V8EXPORT StringObject : public Object {
+class V8_EXPORT StringObject : public Object {
  public:
   static Local<Value> New(Handle<String> value);
 
@@ -2824,7 +2885,7 @@ class V8EXPORT StringObject : public Object {
  *
  * This is an experimental feature. Use at your own risk.
  */
-class V8EXPORT SymbolObject : public Object {
+class V8_EXPORT SymbolObject : public Object {
  public:
   static Local<Value> New(Isolate* isolate, Handle<Symbol> value);
 
@@ -2847,7 +2908,7 @@ class V8EXPORT SymbolObject : public Object {
 /**
  * An instance of the built-in RegExp constructor (ECMA-262, 15.10).
  */
-class V8EXPORT RegExp : public Object {
+class V8_EXPORT RegExp : public Object {
  public:
   /**
    * Regular expression flag bits. They can be or'ed to enable a set
@@ -2894,7 +2955,7 @@ class V8EXPORT 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 V8EXPORT External : public Value {
+class V8_EXPORT External : public Value {
  public:
   static Local<External> New(void* value);
   V8_INLINE(static External* Cast(Value* obj));
@@ -2910,7 +2971,7 @@ class V8EXPORT External : public Value {
 /**
  * The superclass of object and function templates.
  */
-class V8EXPORT Template : public Data {
+class V8_EXPORT Template : public Data {
  public:
   /** Adds a property to each instance created by this template.*/
   void Set(Handle<String> name, Handle<Data> value,
@@ -2998,7 +3059,7 @@ class FunctionCallbackInfo {
 };
 
 
-class V8EXPORT Arguments : public FunctionCallbackInfo<Value> {
+class V8_EXPORT Arguments : public FunctionCallbackInfo<Value> {
  private:
   friend class internal::FunctionCallbackArguments;
   V8_INLINE(Arguments(internal::Object** implicit_args,
@@ -3039,7 +3100,7 @@ class PropertyCallbackInfo {
 };
 
 
-class V8EXPORT AccessorInfo : public PropertyCallbackInfo<Value> {
+class V8_EXPORT AccessorInfo : public PropertyCallbackInfo<Value> {
  private:
   friend class internal::PropertyCallbackArguments;
   V8_INLINE(AccessorInfo(internal::Object** args))
@@ -3287,7 +3348,7 @@ typedef bool (*IndexedSecurityCallback)(Local<Object> host,
  *   child_instance.instance_property == 3;
  * \endcode
  */
-class V8EXPORT FunctionTemplate : public Template {
+class V8_EXPORT FunctionTemplate : public Template {
  public:
   /** Creates a function template.*/
   V8_DEPRECATED(static Local<FunctionTemplate> New(
@@ -3378,7 +3439,7 @@ class V8EXPORT FunctionTemplate : public Template {
  * Properties added to an ObjectTemplate are added to each object
  * created from the ObjectTemplate.
  */
-class V8EXPORT ObjectTemplate : public Template {
+class V8_EXPORT ObjectTemplate : public Template {
  public:
   /** Creates an ObjectTemplate. */
   static Local<ObjectTemplate> New();
@@ -3564,7 +3625,7 @@ class V8EXPORT ObjectTemplate : public Template {
  * A Signature specifies which receivers and arguments are valid
  * parameters to a function.
  */
-class V8EXPORT Signature : public Data {
+class V8_EXPORT Signature : public Data {
  public:
   static Local<Signature> New(Handle<FunctionTemplate> receiver =
                                   Handle<FunctionTemplate>(),
@@ -3579,7 +3640,7 @@ class V8EXPORT Signature : public Data {
  * An AccessorSignature specifies which receivers are valid parameters
  * to an accessor callback.
  */
-class V8EXPORT AccessorSignature : public Data {
+class V8_EXPORT AccessorSignature : public Data {
  public:
   static Local<AccessorSignature> New(Handle<FunctionTemplate> receiver =
                                           Handle<FunctionTemplate>());
@@ -3588,13 +3649,13 @@ class V8EXPORT AccessorSignature : public Data {
 };
 
 
-class V8EXPORT DeclaredAccessorDescriptor : public Data {
+class V8_EXPORT DeclaredAccessorDescriptor : public Data {
  private:
   DeclaredAccessorDescriptor();
 };
 
 
-class V8EXPORT ObjectOperationDescriptor : public Data {
+class V8_EXPORT ObjectOperationDescriptor : public Data {
  public:
   // This function is not yet stable and should not be used at this time.
   static Local<RawOperationDescriptor> NewInternalFieldDereference(
@@ -3614,7 +3675,7 @@ enum DeclaredAccessorDescriptorDataType {
 };
 
 
-class V8EXPORT RawOperationDescriptor : public Data {
+class V8_EXPORT RawOperationDescriptor : public Data {
  public:
   Local<DeclaredAccessorDescriptor> NewHandleDereference(Isolate* isolate);
   Local<RawOperationDescriptor> NewRawDereference(Isolate* isolate);
@@ -3647,7 +3708,7 @@ class V8EXPORT RawOperationDescriptor : public Data {
  * A utility for determining the type of objects based on the template
  * they were constructed from.
  */
-class V8EXPORT TypeSwitch : public Data {
+class V8_EXPORT TypeSwitch : public Data {
  public:
   static Local<TypeSwitch> New(Handle<FunctionTemplate> type);
   static Local<TypeSwitch> New(int argc, Handle<FunctionTemplate> types[]);
@@ -3659,7 +3720,7 @@ class V8EXPORT TypeSwitch : public Data {
 
 // --- Extensions ---
 
-class V8EXPORT ExternalAsciiStringResourceImpl
+class V8_EXPORT ExternalAsciiStringResourceImpl
     : public String::ExternalAsciiStringResource {
  public:
   ExternalAsciiStringResourceImpl() : data_(0), length_(0) {}
@@ -3676,7 +3737,7 @@ class V8EXPORT ExternalAsciiStringResourceImpl
 /**
  * Ignore
  */
-class V8EXPORT Extension {  // NOLINT
+class V8_EXPORT Extension {  // NOLINT
  public:
   // Note that the strings passed into this constructor must live as long
   // as the Extension itself.
@@ -3714,13 +3775,13 @@ class V8EXPORT Extension {  // NOLINT
 };
 
 
-void V8EXPORT RegisterExtension(Extension* extension);
+void V8_EXPORT RegisterExtension(Extension* extension);
 
 
 /**
  * Ignore
  */
-class V8EXPORT DeclareExtension {
+class V8_EXPORT DeclareExtension {
  public:
   V8_INLINE(DeclareExtension(Extension* extension)) {
     RegisterExtension(extension);
@@ -3731,10 +3792,10 @@ class V8EXPORT DeclareExtension {
 // --- Statics ---
 
 
-Handle<Primitive> V8EXPORT Undefined();
-Handle<Primitive> V8EXPORT Null();
-Handle<Boolean> V8EXPORT True();
-Handle<Boolean> V8EXPORT False();
+Handle<Primitive> V8_EXPORT Undefined();
+Handle<Primitive> V8_EXPORT Null();
+Handle<Boolean> V8_EXPORT True();
+Handle<Boolean> V8_EXPORT False();
 
 V8_INLINE(Handle<Primitive> Undefined(Isolate* isolate));
 V8_INLINE(Handle<Primitive> Null(Isolate* isolate));
@@ -3751,7 +3812,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 V8EXPORT ResourceConstraints {
+class V8_EXPORT ResourceConstraints {
  public:
   ResourceConstraints();
   int max_young_space_size() const { return max_young_space_size_; }
@@ -3771,7 +3832,7 @@ class V8EXPORT ResourceConstraints {
 };
 
 
-bool V8EXPORT SetResourceConstraints(ResourceConstraints* constraints);
+bool V8_EXPORT SetResourceConstraints(ResourceConstraints* constraints);
 
 
 // --- Exceptions ---
@@ -3789,13 +3850,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> V8EXPORT ThrowException(Handle<Value> exception);
+Handle<Value> V8_EXPORT ThrowException(Handle<Value> exception);
 
 /**
  * Create new error objects by calling the corresponding error object
  * constructor with the message.
  */
-class V8EXPORT Exception {
+class V8_EXPORT Exception {
  public:
   static Local<Value> RangeError(Handle<String> message);
   static Local<Value> ReferenceError(Handle<String> message);
@@ -3889,7 +3950,7 @@ typedef void (*GCCallback)();
  * Instances of this class can be passed to v8::V8::HeapStatistics to
  * get heap statistics from V8.
  */
-class V8EXPORT HeapStatistics {
+class V8_EXPORT HeapStatistics {
  public:
   HeapStatistics();
   size_t total_heap_size() { return total_heap_size_; }
@@ -3921,13 +3982,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 V8EXPORT Isolate {
+class V8_EXPORT Isolate {
  public:
   /**
    * Stack-allocated class which sets the isolate for all operations
    * executed within a local scope.
    */
-  class V8EXPORT Scope {
+  class V8_EXPORT Scope {
    public:
     explicit Scope(Isolate* isolate) : isolate_(isolate) {
       isolate->Enter();
@@ -4075,7 +4136,7 @@ class V8EXPORT Isolate {
 };
 
 
-class V8EXPORT StartupData {
+class V8_EXPORT StartupData {
  public:
   enum CompressionAlgorithm {
     kUncompressed,
@@ -4096,7 +4157,7 @@ class V8EXPORT StartupData {
  *
  * For an example of the class usage, see the "shell.cc" sample application.
  */
-class V8EXPORT StartupDataDecompressor {  // NOLINT
+class V8_EXPORT StartupDataDecompressor {  // NOLINT
  public:
   StartupDataDecompressor();
   virtual ~StartupDataDecompressor();
@@ -4240,7 +4301,7 @@ typedef void (*JitCodeEventHandler)(const JitCodeEvent* event);
 /**
  * Interface for iterating through all external resources in the heap.
  */
-class V8EXPORT ExternalResourceVisitor {  // NOLINT
+class V8_EXPORT ExternalResourceVisitor {  // NOLINT
  public:
   virtual ~ExternalResourceVisitor() {}
   virtual void VisitExternalString(Handle<String> string) {}
@@ -4250,7 +4311,7 @@ class V8EXPORT ExternalResourceVisitor {  // NOLINT
 /**
  * Interface for iterating through all the persistent handles in the heap.
  */
-class V8EXPORT PersistentHandleVisitor {  // NOLINT
+class V8_EXPORT PersistentHandleVisitor {  // NOLINT
  public:
   virtual ~PersistentHandleVisitor() {}
   virtual void VisitPersistentHandle(Persistent<Value>* value,
@@ -4263,7 +4324,7 @@ class V8EXPORT PersistentHandleVisitor {  // NOLINT
  * to be modified. Useful when otherwise unsafe handle operations need to
  * be performed.
  */
-class V8EXPORT AssertNoGCScope {
+class V8_EXPORT AssertNoGCScope {
 #ifndef DEBUG
   // TODO(yangguo): remove isolate argument.
   V8_INLINE(AssertNoGCScope(Isolate* isolate)) { }
@@ -4279,7 +4340,7 @@ class V8EXPORT AssertNoGCScope {
 /**
  * Container class for static utility functions.
  */
-class V8EXPORT V8 {
+class V8_EXPORT V8 {
  public:
   /** Set the callback to invoke in case of fatal errors. */
   static void SetFatalErrorHandler(FatalErrorCallback that);
@@ -4736,6 +4797,9 @@ class V8EXPORT 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;
@@ -4747,7 +4811,7 @@ class V8EXPORT V8 {
 /**
  * An external exception handler.
  */
-class V8EXPORT TryCatch {
+class V8_EXPORT TryCatch {
  public:
   /**
    * Creates a new try/catch block and registers it with v8.  Note that
@@ -4880,7 +4944,7 @@ class V8EXPORT TryCatch {
 /**
  * Ignore
  */
-class V8EXPORT ExtensionConfiguration {
+class V8_EXPORT ExtensionConfiguration {
  public:
   ExtensionConfiguration(int name_count, const char* names[])
       : name_count_(name_count), names_(names) { }
@@ -4895,7 +4959,7 @@ class V8EXPORT ExtensionConfiguration {
  * A sandboxed execution context with its own set of built-in objects
  * and functions.
  */
-class V8EXPORT Context {
+class V8_EXPORT Context {
  public:
   /**
    * Returns the global proxy object or global object itself for
@@ -5180,7 +5244,7 @@ class V8EXPORT Context {
  * // V8 Now no longer locked.
  * \endcode
  */
-class V8EXPORT Unlocker {
+class V8_EXPORT Unlocker {
  public:
   /**
    * Initialize Unlocker for a given Isolate.
@@ -5198,7 +5262,7 @@ class V8EXPORT Unlocker {
 };
 
 
-class V8EXPORT Locker {
+class V8_EXPORT Locker {
  public:
   /**
    * Initialize Locker for a given Isolate.
@@ -5259,7 +5323,7 @@ struct HeapStatsUpdate;
 /**
  * An interface for exporting data from V8, using "push" model.
  */
-class V8EXPORT OutputStream {  // NOLINT
+class V8_EXPORT OutputStream {  // NOLINT
  public:
   enum OutputEncoding {
     kAscii = 0  // 7-bit ASCII.
@@ -5296,7 +5360,7 @@ class V8EXPORT OutputStream {  // NOLINT
  * An interface for reporting progress and controlling long-running
  * activities.
  */
-class V8EXPORT ActivityControl {  // NOLINT
+class V8_EXPORT ActivityControl {  // NOLINT
  public:
   enum ControlOption {
     kContinue = 0,
@@ -5419,12 +5483,13 @@ class Internals {
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 134;
+  static const int kEmptyStringRootIndex = 133;
 
   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
   static const int kNodeStateMask = 0xf;
   static const int kNodeStateIsWeakValue = 2;
+  static const int kNodeStateIsPendingValue = 3;
   static const int kNodeStateIsNearDeathValue = 4;
   static const int kNodeIsIndependentShift = 4;
   static const int kNodeIsPartiallyDependentShift = 5;
@@ -5598,6 +5663,21 @@ 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) {
@@ -5640,8 +5720,10 @@ template <class T>
 bool Persistent<T>::IsNearDeath() const {
   typedef internal::Internals I;
   if (this->IsEmpty()) return false;
-  return I::GetNodeState(reinterpret_cast<internal::Object**>(this->val_)) ==
-      I::kNodeStateIsNearDeathValue;
+  uint8_t node_state =
+      I::GetNodeState(reinterpret_cast<internal::Object**>(this->val_));
+  return node_state == I::kNodeStateIsNearDeathValue ||
+      node_state == I::kNodeStateIsPendingValue;
 }
 
 
@@ -5996,6 +6078,10 @@ Handle<Integer> ScriptOrigin::ResourceColumnOffset() const {
   return resource_column_offset_;
 }
 
+Handle<Boolean> ScriptOrigin::ResourceIsSharedCrossOrigin() const {
+  return resource_is_shared_cross_origin_;
+}
+
 
 Handle<Boolean> Boolean::New(bool value) {
   return value ? True() : False();
@@ -6503,7 +6589,6 @@ void* Context::GetAlignedPointerFromEmbedderData(int index) {
 }  // namespace v8
 
 
-#undef V8EXPORT
 #undef TYPE_CHECK
 
 
index d587b81..e04fbef 100644 (file)
@@ -46,6 +46,7 @@
 #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"
@@ -398,7 +399,7 @@ enum CompressedStartupDataItems {
   kSnapshotContext,
   kLibraries,
   kExperimentalLibraries,
-#if defined(ENABLE_I18N_SUPPORT)
+#if defined(V8_I18N_SUPPORT)
   kI18NExtension,
 #endif
   kCompressedStartupDataCount
@@ -442,7 +443,7 @@ void V8::GetCompressedStartupData(StartupData* compressed_data) {
   compressed_data[kExperimentalLibraries].raw_size =
       i::ExperimentalNatives::GetRawScriptsSize();
 
-#if defined(ENABLE_I18N_SUPPORT)
+#if defined(V8_I18N_SUPPORT)
   i::Vector<const ii:byte> i18n_extension_source =
       i::I18NNatives::GetScriptsSource();
   compressed_data[kI18NExtension].data =
@@ -482,7 +483,7 @@ void V8::SetDecompressedStartupData(StartupData* decompressed_data) {
       decompressed_data[kExperimentalLibraries].raw_size);
   i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
 
-#if defined(ENABLE_I18N_SUPPORT)
+#if defined(V8_I18N_SUPPORT)
   ASSERT_EQ(i::I18NNatives::GetRawScriptsSize(),
             decompressed_data[kI18NExtension].raw_size);
   i::Vector<const char> i18n_extension_source(
@@ -675,6 +676,16 @@ 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 ---
 
 
@@ -1918,6 +1929,7 @@ Local<Script> Script::New(v8::Handle<String> source,
     i::Handle<i::Object> name_obj;
     int line_offset = 0;
     int column_offset = 0;
+    bool is_shared_cross_origin = false;
     if (origin != NULL) {
       if (!origin->ResourceName().IsEmpty()) {
         name_obj = Utils::OpenHandle(*origin->ResourceName());
@@ -1929,6 +1941,10 @@ Local<Script> Script::New(v8::Handle<String> source,
         column_offset =
             static_cast<int>(origin->ResourceColumnOffset()->Value());
       }
+      if (!origin->ResourceIsSharedCrossOrigin().IsEmpty()) {
+        is_shared_cross_origin =
+            origin->ResourceIsSharedCrossOrigin() == v8::True();
+      }
     }
     EXCEPTION_PREAMBLE(isolate);
     i::ScriptDataImpl* pre_data_impl =
@@ -1945,6 +1961,7 @@ Local<Script> Script::New(v8::Handle<String> source,
                            name_obj,
                            line_offset,
                            column_offset,
+                           is_shared_cross_origin,
                            isolate->global_context(),
                            NULL,
                            pre_data_impl,
@@ -2412,6 +2429,20 @@ int Message::GetEndColumn() const {
 }
 
 
+bool Message::IsSharedCrossOrigin() const {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::IsSharedCrossOrigin()")) return 0;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  i::Handle<i::JSValue> script =
+      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
+                                                       isolate));
+  return i::Script::cast(script->value())->is_shared_cross_origin();
+}
+
+
 Local<String> Message::GetSourceLine() const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
@@ -2587,6 +2618,29 @@ bool StackFrame::IsConstructor() const {
 }
 
 
+// --- J S O N ---
+
+Local<Object> 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::JSObject>::cast(scope.CloseAndEscape(result)));
+}
+
+
 // --- D a t a ---
 
 bool Value::FullIsUndefined() const {
@@ -3051,6 +3105,12 @@ void v8::ArrayBuffer::CheckCast(Value* that) {
 }
 
 
+void v8::ArrayBuffer::Allocator::Free(void* data) {
+  API_Fatal("v8::ArrayBuffer::Allocator::Free",
+            "Override Allocator::Free(void*, size_t)");
+}
+
+
 void v8::ArrayBufferView::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsJSArrayBufferView(),
@@ -7541,6 +7601,18 @@ const CpuProfileNode* CpuProfile::GetSample(int index) const {
 }
 
 
+int64_t CpuProfile::GetStartTime() const {
+  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
+  return profile->start_time_us();
+}
+
+
+int64_t CpuProfile::GetEndTime() const {
+  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
+  return profile->end_time_us();
+}
+
+
 int CpuProfile::GetSamplesCount() const {
   return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
 }
index ba0dc4b..a9db5a5 100644 (file)
@@ -764,10 +764,13 @@ int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
 // Linked labels refer to unknown positions in the code
 // to be generated; pos() is the position of the last
 // instruction using the label.
-
-
-// The link chain is terminated by a negative code position (must be aligned)
-const int kEndOfChain = -4;
+//
+// The linked labels form a link chain by making the branch offset
+// in the instruction steam to point to the previous branch
+// instruction using the same label.
+//
+// The link chain is terminated by a branch offset pointing to the
+// same position.
 
 
 int Assembler::target_at(int pos)  {
@@ -790,7 +793,7 @@ int Assembler::target_at(int pos)  {
 void Assembler::target_at_put(int pos, int target_pos) {
   Instr instr = instr_at(pos);
   if ((instr & ~kImm24Mask) == 0) {
-    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
+    ASSERT(target_pos == pos || target_pos >= 0);
     // Emitted label constant, not part of a branch.
     // Make label relative to Code* of generated Code object.
     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
@@ -886,27 +889,6 @@ void Assembler::bind_to(Label* L, int pos) {
 }
 
 
-void Assembler::link_to(Label* L, Label* appendix) {
-  if (appendix->is_linked()) {
-    if (L->is_linked()) {
-      // Append appendix to L's list.
-      int fixup_pos;
-      int link = L->pos();
-      do {
-        fixup_pos = link;
-        link = target_at(fixup_pos);
-      } while (link > 0);
-      ASSERT(link == kEndOfChain);
-      target_at_put(fixup_pos, appendix->pos());
-    } else {
-      // L is empty, simply use appendix.
-      *L = *appendix;
-    }
-  }
-  appendix->Unuse();  // appendix should not be used anymore
-}
-
-
 void Assembler::bind(Label* L) {
   ASSERT(!L->is_bound());  // label can only be bound once
   bind_to(L, pc_offset());
@@ -916,7 +898,9 @@ void Assembler::bind(Label* L) {
 void Assembler::next(Label* L) {
   ASSERT(L->is_linked());
   int link = target_at(L->pos());
-  if (link == kEndOfChain) {
+  if (link == L->pos()) {
+    // Branch target points to the same instuction. This is the end of the link
+    // chain.
     L->Unuse();
   } else {
     ASSERT(link >= 0);
@@ -1229,9 +1213,11 @@ int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
     target_pos = L->pos();
   } else {
     if (L->is_linked()) {
-      target_pos = L->pos();  // L's link
+      // Point to previous instruction that uses the link.
+      target_pos = L->pos();
     } else {
-      target_pos = kEndOfChain;
+      // First entry of the link chain points to itself.
+      target_pos = pc_offset();
     }
     L->link_to(pc_offset());
   }
@@ -1245,17 +1231,16 @@ int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
 
 void Assembler::label_at_put(Label* L, int at_offset) {
   int target_pos;
-  if (L->is_bound()) {
+  ASSERT(!L->is_bound());
+  if (L->is_linked()) {
+    // Point to previous instruction that uses the link.
     target_pos = L->pos();
   } else {
-    if (L->is_linked()) {
-      target_pos = L->pos();  // L's link
-    } else {
-      target_pos = kEndOfChain;
-    }
-    L->link_to(at_offset);
-    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
+    // First entry of the link chain points to itself.
+    target_pos = at_offset;
   }
+  L->link_to(at_offset);
+  instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
 }
 
 
index 496eb3e..f647848 100644 (file)
@@ -1548,7 +1548,6 @@ class Assembler : public AssemblerBase {
   // Labels
   void print(Label* L);
   void bind_to(Label* L, int pos);
-  void link_to(Label* L, Label* appendix);
   void next(Label* L);
 
   enum UseConstantPoolMode {
index eff47e2..5f3a999 100644 (file)
@@ -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, "Unexpected initial map for InternalArray function");
+    __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction);
     __ CompareObjectType(r2, r3, r4, MAP_TYPE);
-    __ Assert(eq, "Unexpected initial map for InternalArray function");
+    __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction);
   }
 
   // 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, "Unexpected initial map for Array function");
+    __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
     __ CompareObjectType(r2, r3, r4, MAP_TYPE);
-    __ Assert(eq, "Unexpected initial map for Array function");
+    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
   }
 
   // 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, "Unexpected String function");
+    __ Assert(eq, kUnexpectedStringFunction);
   }
 
   // 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, "Unexpected string wrapper instance size");
+    __ Assert(eq, kUnexpectedStringWrapperInstanceSize);
     __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
     __ cmp(r4, Operand::Zero());
-    __ Assert(eq, "Unexpected unused properties of string wrapper");
+    __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper);
   }
   __ 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, "Unexpected number of pre-allocated property fields.");
+          __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
         }
         __ 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, "Property allocation count failed.");
+      __ Assert(pl, kPropertyAllocationCountFailed);
 
       // 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, "Undefined value not loaded.");
+          __ Assert(eq, kUndefinedValueNotLoaded);
         }
         __ b(&entry);
         __ bind(&loop);
index ba98b96..98a835f 100644 (file)
@@ -246,17 +246,6 @@ 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) {
@@ -520,9 +509,8 @@ 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, message);
+    __ Assert(eq, kExpected0AsASmiSentinel);
   }
   __ ldr(r3, GlobalObjectOperand());
   __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
@@ -3917,9 +3905,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
   if (FLAG_debug_code) {
     __ SmiTst(regexp_data);
-    __ Check(ne, "Unexpected type for RegExp data, FixedArray expected");
+    __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected);
     __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
-    __ Check(eq, "Unexpected type for RegExp data, FixedArray expected");
+    __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
   }
 
   // regexp_data: RegExp data (FixedArray)
@@ -4261,7 +4249,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, "external string expected, but not found");
+    __ Assert(eq, kExternalStringExpectedButNotFound);
   }
   __ ldr(subject,
          FieldMemOperand(subject, ExternalString::kResourceDataOffset));
@@ -4643,7 +4631,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharCodeAtGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
 
   // Index is not a smi.
   __ bind(&index_not_smi_);
@@ -4688,7 +4676,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
 }
 
 
@@ -4718,7 +4706,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharFromCodeGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
 
   __ bind(&slow_case_);
   call_helper.BeforeCall(masm);
@@ -4728,7 +4716,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
 }
 
 
@@ -4785,7 +4773,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, "Destination of copy not aligned.");
+    __ Check(eq, kDestinationOfCopyNotAligned);
   }
 
   const int kReadAlignment = 4;
@@ -5014,7 +5002,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
     if (FLAG_debug_code) {
       __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
       __ cmp(ip, candidate);
-      __ Assert(eq, "oddball in string table is not undefined or the hole");
+      __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole);
     }
     __ jmp(&next_probe[i]);
 
@@ -6912,7 +6900,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -6969,7 +6957,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -7030,9 +7018,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, "Unexpected initial map for Array function");
+    __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
     __ CompareObjectType(r3, r3, r4, MAP_TYPE);
-    __ Assert(eq, "Unexpected initial map for Array function");
+    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
 
     // We should either have undefined in ebx or a valid cell
     Label okay_here;
@@ -7041,7 +7029,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ b(eq, &okay_here);
     __ ldr(r3, FieldMemOperand(r2, 0));
     __ cmp(r3, Operand(cell_map));
-    __ Assert(eq, "Expected property cell in register ebx");
+    __ Assert(eq, kExpectedPropertyCellInRegisterEbx);
     __ bind(&okay_here);
   }
 
@@ -7144,9 +7132,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, "Unexpected initial map for Array function");
+    __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
     __ CompareObjectType(r3, r3, r4, MAP_TYPE);
-    __ Assert(eq, "Unexpected initial map for Array function");
+    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
   }
 
   // Figure out the right elements kind
@@ -7163,7 +7151,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ b(eq, &done);
     __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS));
     __ Assert(eq,
-              "Invalid ElementsKind for InternalArray or InternalPackedArray");
+              kInvalidElementsKindForInternalArrayOrInternalPackedArray);
     __ bind(&done);
   }
 
index 7559373..1bcf3e3 100644 (file)
@@ -532,7 +532,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
     __ SmiTag(r9);
     __ orr(r9, r9, Operand(1));
     __ CompareRoot(r9, Heap::kTheHoleValueRootIndex);
-    __ Assert(eq, "object found in smi-only array");
+    __ Assert(eq, kObjectFoundInSmiOnlyArray);
   }
   __ 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, "external string expected, but not found");
+    __ Assert(eq, kExternalStringExpectedButNotFound);
   }
   // Rule out short external strings.
   STATIC_CHECK(kShortExternalStringTag != 0);
index 7faea08..108435f 100644 (file)
@@ -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, "Unable to encode value as smi");
+            __ Assert(eq, kUnableToEncodeValueAsSmi);
           }
           __ SmiTag(reg);
         }
@@ -313,12 +313,12 @@ void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
 
 
 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on arm");
+  masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnArm);
 }
 
 
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on arm");
+  masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnArm);
 }
 
 const bool Debug::kFrameDropperSupported = false;
index 19b29b8..d022b41 100644 (file)
@@ -171,6 +171,11 @@ inline Object* JavaScriptFrame::function_slot_object() const {
 }
 
 
+inline void StackHandler::SetFp(Address slot, Address fp) {
+  Memory::Address_at(slot) = fp;
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_ARM_FRAMES_ARM_H_
index ea7b73f..b73006a 100644 (file)
@@ -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, "Declaration in with context.");
+    __ Check(ne, kDeclarationInWithContext);
     __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
-    __ Check(ne, "Declaration in catch context.");
+    __ Check(ne, kDeclarationInCatchContext);
   }
 }
 
@@ -2512,7 +2512,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         // Check for an uninitialized let binding.
         __ ldr(r2, location);
         __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
-        __ Check(eq, "Let binding re-initialization.");
+        __ Check(eq, kLetBindingReInitialization);
       }
       // 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, "Non-smi index");
+  __ Check(eq, kNonSmiIndex);
   __ SmiTst(value);
-  __ Check(eq, "Non-smi value");
+  __ Check(eq, kNonSmiValue);
 
   __ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
   __ cmp(index, ip);
-  __ Check(lt, "Index is too large");
+  __ Check(lt, kIndexIsTooLarge);
 
   __ cmp(index, Operand(Smi::FromInt(0)));
-  __ Check(ge, "Index is negative");
+  __ Check(ge, kIndexIsNegative);
 
   __ 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, "Unexpected string type");
+  __ Check(eq, kUnexpectedStringType);
 }
 
 
@@ -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("Attempt to use undefined cache.");
+    __ Abort(kAttemptToUseUndefinedCache);
     __ 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, "No empty arrays here in EmitFastAsciiArrayJoin");
+    __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
   }
   __ bind(&loop);
   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
@@ -4349,35 +4349,12 @@ 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());
index b55679e..43f0fd3 100644 (file)
@@ -272,24 +272,6 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) {
 }
 
 
-ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) {
-  switch (hydrogen()->known_list()) {
-    case HLinkObjectInList::ALLOCATION_SITE_LIST:
-      return ExternalReference::allocation_sites_list_address(isolate);
-  }
-
-  UNREACHABLE();
-  // Return a dummy value
-  return ExternalReference::isolate_address(isolate);
-}
-
-
-void LLinkObjectInList::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add(" offset %d", hydrogen()->store_field().offset());
-}
-
-
 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
   context()->PrintTo(stream);
   stream->Add("[%d]", slot_index());
@@ -455,7 +437,7 @@ LPlatformChunk* LChunkBuilder::Build() {
 }
 
 
-void LChunkBuilder::Abort(const char* reason) {
+void LChunkBuilder::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -663,7 +645,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
   int vreg = allocator_->GetVirtualRegister();
   if (!allocator_->AllocationOk()) {
-    Abort("Out of virtual registers while trying to allocate temp register.");
+    Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
     vreg = 0;
   }
   operand->set_virtual_register(vreg);
@@ -1343,15 +1325,6 @@ 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);
@@ -1850,17 +1823,6 @@ 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());
@@ -2034,19 +1996,6 @@ 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));
@@ -2055,10 +2004,16 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
 
 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
   LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
-  LInstruction* result = new(zone()) LCheckMaps(value);
-  if (instr->CanOmitMapChecks()) return result;
-  return AssignEnvironment(result);
+  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;
 }
 
 
@@ -2140,13 +2095,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) {
-  LOperand* object = UseRegister(instr->value());
-  LLinkObjectInList* result = new(zone()) LLinkObjectInList(object);
-  return result;
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
@@ -2347,7 +2295,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->transition().is_null() &&
+  bool needs_write_barrier_for_map = instr->has_transition() &&
       instr->NeedsWriteBarrierForMap();
 
   LOperand* obj;
@@ -2418,12 +2366,6 @@ LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
-  LOperand* string = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   info()->MarkAsDeferredCalling();
   LOperand* size = instr->size()->IsConstant()
@@ -2473,7 +2415,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("Too many spill slots needed for OSR");
+    Abort(kTooManySpillSlotsNeededForOSR);
     spill_index = 0;
   }
   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
index eecacec..7ce907a 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -68,7 +67,6 @@ class LCodeGen;
   V(CheckNonSmi)                                \
   V(CheckMaps)                                  \
   V(CheckMapValue)                              \
-  V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
@@ -119,7 +117,6 @@ class LCodeGen;
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
   V(LazyBailout)                                \
-  V(LinkObjectInList)                           \
   V(LoadContextSlot)                            \
   V(LoadExternalArrayPointer)                   \
   V(LoadFieldByIndex)                           \
@@ -176,7 +173,6 @@ class LCodeGen;
   V(StringCharCodeAt)                           \
   V(StringCharFromCode)                         \
   V(StringCompareAndBranch)                     \
-  V(StringLength)                               \
   V(SubI)                                       \
   V(RSubI)                                      \
   V(TaggedToI)                                  \
@@ -1380,18 +1376,6 @@ 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) {
@@ -1676,23 +1660,6 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> {
 };
 
 
-class LLinkObjectInList: public LTemplateInstruction<0, 1, 0> {
- public:
-  explicit LLinkObjectInList(LOperand* object) {
-    inputs_[0] = object;
-  }
-
-  LOperand* object() { return inputs_[0]; }
-
-  ExternalReference GetReference(Isolate* isolate);
-
-  DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list")
-  DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList)
-
-  virtual void PrintDataTo(StringStream* stream);
-};
-
-
 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
@@ -2169,7 +2136,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
 
   virtual void PrintDataTo(StringStream* stream);
 
-  Handle<Map> transition() const { return hydrogen()->transition(); }
+  Handle<Map> transition() const { return hydrogen()->transition_map(); }
   Representation representation() const {
     return hydrogen()->field_representation();
   }
@@ -2332,19 +2299,6 @@ class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
 };
 
 
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LStringLength(LOperand* string) {
-    inputs_[0] = string;
-  }
-
-  LOperand* string() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
-  DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
 class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckFunction(LOperand* value) {
@@ -2384,26 +2338,6 @@ 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) {
@@ -2702,7 +2636,7 @@ class LChunkBuilder BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
 
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
index 929d04d..0b704d0 100644 (file)
@@ -91,7 +91,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
 }
 
 
-void LCodeGen::Abort(const char* reason) {
+void LCodeGen::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -334,7 +334,7 @@ bool LCodeGen::GenerateDeoptJumpTable() {
   // 32bit data after it.
   if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) +
       deopt_jump_table_.length() * 7)) {
-    Abort("Generated code is too large");
+    Abort(kGeneratedCodeIsTooLarge);
   }
 
   if (deopt_jump_table_.length() > 0) {
@@ -423,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("EmitLoadRegister: Unsupported double immediate.");
+      Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
     } else {
       ASSERT(r.IsTagged());
       __ LoadObject(scratch, literal);
@@ -461,9 +461,9 @@ DwVfpRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
       __ vcvt_f64_s32(dbl_scratch, flt_scratch);
       return dbl_scratch;
     } else if (r.IsDouble()) {
-      Abort("unsupported double immediate");
+      Abort(kUnsupportedDoubleImmediate);
     } else if (r.IsTagged()) {
-      Abort("unsupported tagged immediate");
+      Abort(kUnsupportedTaggedImmediate);
     }
   } else if (op->IsStackSlot() || op->IsArgument()) {
     // TODO(regis): Why is vldr not taking a MemOperand?
@@ -534,14 +534,14 @@ Operand LCodeGen::ToOperand(LOperand* op) {
       ASSERT(constant->HasInteger32Value());
       return Operand(constant->Integer32Value());
     } else if (r.IsDouble()) {
-      Abort("ToOperand Unsupported double immediate.");
+      Abort(kToOperandUnsupportedDoubleImmediate);
     }
     ASSERT(r.IsTagged());
     return Operand(constant->handle());
   } else if (op->IsRegister()) {
     return Operand(ToRegister(op));
   } else if (op->IsDoubleRegister()) {
-    Abort("ToOperand IsDoubleRegister unimplemented");
+    Abort(kToOperandIsDoubleRegisterUnimplemented);
     return Operand::Zero();
   }
   // Stack slots not implemented, use ToMemOperand instead.
@@ -772,7 +772,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
   Address entry =
       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
   if (entry == NULL) {
-    Abort("bailout was not prepared");
+    Abort(kBailoutWasNotPrepared);
     return;
   }
 
@@ -1669,7 +1669,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
       __ orr(result, left, right);
       break;
     case Token::BIT_XOR:
-      __ eor(result, left, right);
+      if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
+        __ mvn(result, Operand(left));
+      } else {
+        __ eor(result, left, right);
+      }
       break;
     default:
       UNREACHABLE();
@@ -1744,8 +1748,12 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
         if (shift_count != 0) {
           if (instr->hydrogen_value()->representation().IsSmi() &&
               instr->can_deopt()) {
-            __ mov(result, Operand(left, LSL, shift_count - 1));
-            __ SmiTag(result, result, SetCC);
+            if (shift_count != 1) {
+              __ mov(result, Operand(left, LSL, shift_count - 1));
+              __ SmiTag(result, result, SetCC);
+            } else {
+              __ SmiTag(result, left, SetCC);
+            }
             DeoptimizeIf(vs, instr->environment());
           } else {
             __ mov(result, Operand(left, LSL, shift_count));
@@ -1932,7 +1940,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, "Unexpected string type");
+    __ Check(eq, kUnexpectedStringType);
   }
 
   __ add(ip,
@@ -1949,13 +1957,6 @@ 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);
@@ -2936,19 +2937,6 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
 }
 
 
-void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) {
-  Register object = ToRegister(instr->object());
-  ExternalReference sites_list_address = instr->GetReference(isolate());
-
-  __ mov(ip, Operand(sites_list_address));
-  __ ldr(ip, MemOperand(ip));
-  __ str(ip, FieldMemOperand(object,
-                             instr->hydrogen()->store_field().offset()));
-  __ mov(ip, Operand(sites_list_address));
-  __ str(object, MemOperand(ip));
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -3209,7 +3197,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -3293,7 +3281,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -3554,7 +3542,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
 void LCodeGen::DoPushArgument(LPushArgument* instr) {
   LOperand* argument = instr->value();
   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
-    Abort("DoPushArgument not implemented for double type.");
+    Abort(kDoPushArgumentNotImplementedForDoubleType);
   } else {
     Register argument_reg = EmitLoadRegister(argument, ip);
     __ push(argument_reg);
@@ -3774,7 +3762,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
     DwVfpRegister input = ToDoubleRegister(instr->value());
     DwVfpRegister result = ToDoubleRegister(instr->result());
     __ vabs(result, input);
-  } else if (r.IsInteger32()) {
+  } else if (r.IsSmiOrInteger32()) {
     EmitIntegerMathAbs(instr);
   } else {
     // Representation is tagged.
@@ -4328,7 +4316,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -4401,7 +4389,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -4424,7 +4412,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
     if (masm()->emit_debug_code()) {
       __ vmrs(ip);
       __ tst(ip, Operand(kVFPDefaultNaNModeControlBit));
-      __ Assert(ne, "Default NaN mode not set");
+      __ Assert(ne, kDefaultNaNModeNotSet);
     }
     __ VFPCanonicalizeNaN(value);
   }
@@ -4654,13 +4642,6 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
 }
 
 
-void LCodeGen::DoStringLength(LStringLength* instr) {
-  Register string = ToRegister(instr->string());
-  Register result = ToRegister(instr->result());
-  __ ldr(result, FieldMemOperand(string, String::kLengthOffset));
-}
-
-
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
   LOperand* input = instr->value();
   ASSERT(input->IsRegister() || input->IsStackSlot());
@@ -5230,33 +5211,67 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
 }
 
 
-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::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::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();
-  DoCheckMapCommon(map_reg, map, instr->environment());
+  __ CompareMap(map_reg, map, &success);
+  if (instr->hydrogen()->has_migration_target()) {
+    __ b(ne, deferred->entry());
+  } else {
+    DeoptimizeIf(ne, instr->environment());
+  }
+
   __ bind(&success);
 }
 
@@ -5311,25 +5326,6 @@ 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:
@@ -5353,10 +5349,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
   }
 
@@ -5415,10 +5413,12 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
     __ Push(Smi::FromInt(size));
   }
 
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
   } else {
     CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
index 21f7921..143109c 100644 (file)
@@ -115,7 +115,7 @@ class LCodeGen BASE_EMBEDDED {
   DwVfpRegister EmitLoadDoubleRegister(LOperand* op,
                                        SwVfpRegister flt_scratch,
                                        DwVfpRegister dbl_scratch);
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
@@ -154,8 +154,7 @@ class LCodeGen BASE_EMBEDDED {
   void DoDeferredAllocate(LAllocate* instr);
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
-
-  void DoCheckMapCommon(Register map_reg, Handle<Map> map, LEnvironment* env);
+  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
 
   // 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(const char* reason);
+  void Abort(BailoutReason reason);
   void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
index 7a3c968..88ac7a2 100644 (file)
@@ -254,7 +254,7 @@ void LGapResolver::EmitMove(int index) {
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
-    } else if (source->IsDoubleRegister()) {
+    } else if (destination->IsDoubleRegister()) {
       DwVfpRegister result = cgen_->ToDoubleRegister(destination);
       double v = cgen_->ToDouble(constant_source);
       __ Vmov(result, v, ip);
index cd12461..b9728ed 100644 (file)
@@ -489,7 +489,7 @@ void MacroAssembler::RecordWrite(Register object,
   if (emit_debug_code()) {
     ldr(ip, MemOperand(address));
     cmp(ip, value);
-    Check(eq, "Wrong address or value passed to RecordWrite");
+    Check(eq, kWrongAddressOrValuePassedToRecordWrite);
   }
 
   Label done;
@@ -1490,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, "we should not have an empty lexical context");
+  Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
 #endif
 
   // Load the native context of the current context.
@@ -1508,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, "JSGlobalObject::native_context should be a native context.");
+    Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
     pop(holder_reg);  // Restore holder.
   }
 
@@ -1525,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, "JSGlobalProxy::context() should not be null.");
+    Check(ne, kJSGlobalProxyContextShouldNotBeNull);
 
     ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
     LoadRoot(ip, Heap::kNativeContextMapRootIndex);
     cmp(holder_reg, ip);
-    Check(eq, "JSGlobalObject::native_context should be a native context.");
+    Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
     // Restore ip is not needed. ip is reloaded below.
     pop(holder_reg);  // Restore holder.
     // Restore ip to holder's context.
@@ -1727,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, "Unexpected allocation top");
+      Check(eq, kUnexpectedAllocationTop);
     }
     // Load allocation limit into ip. Result already contains allocation top.
     ldr(ip, MemOperand(topaddr, limit - top));
@@ -1825,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, "Unexpected allocation top");
+      Check(eq, kUnexpectedAllocationTop);
     }
     // Load allocation limit into ip. Result already contains allocation top.
     ldr(ip, MemOperand(topaddr, limit - top));
@@ -1859,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, "Unaligned allocation in new space");
+    Check(eq, kUnalignedAllocationInNewSpace);
   }
   str(scratch2, MemOperand(topaddr));
 
@@ -1882,7 +1882,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object,
   mov(scratch, Operand(new_space_allocation_top));
   ldr(scratch, MemOperand(scratch));
   cmp(object, scratch);
-  Check(lt, "Undo allocation of non allocated memory");
+  Check(lt, kUndoAllocationOfNonAllocatedMemory);
 #endif
   // Write the address of the object to un-allocate as the current top.
   mov(scratch, Operand(new_space_allocation_top));
@@ -2131,7 +2131,7 @@ void MacroAssembler::StoreNumberToDoubleElements(
   if (emit_debug_code()) {
     vmrs(ip);
     tst(ip, Operand(kVFPDefaultNaNModeControlBit));
-    Assert(ne, "Default NaN mode not set");
+    Assert(ne, kDefaultNaNModeNotSet);
   }
   VFPCanonicalizeNaN(double_scratch);
   b(&store);
@@ -2381,7 +2381,7 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
   if (emit_debug_code()) {
     ldr(r1, MemOperand(r7, kLevelOffset));
     cmp(r1, r6);
-    Check(eq, "Unexpected level after return from api call");
+    Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
   }
   sub(r6, r6, Operand(1));
   str(r6, MemOperand(r7, kLevelOffset));
@@ -2782,9 +2782,9 @@ void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
 }
 
 
-void MacroAssembler::Assert(Condition cond, const char* msg) {
+void MacroAssembler::Assert(Condition cond, BailoutReason reason) {
   if (emit_debug_code())
-    Check(cond, msg);
+    Check(cond, reason);
 }
 
 
@@ -2803,23 +2803,23 @@ void MacroAssembler::AssertFastElements(Register elements) {
     LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
     cmp(elements, ip);
     b(eq, &ok);
-    Abort("JSObject with fast elements map has slow elements");
+    Abort(kJSObjectWithFastElementsMapHasSlowElements);
     bind(&ok);
     pop(elements);
   }
 }
 
 
-void MacroAssembler::Check(Condition cond, const char* msg) {
+void MacroAssembler::Check(Condition cond, BailoutReason reason) {
   Label L;
   b(cond, &L);
-  Abort(msg);
+  Abort(reason);
   // will not return here
   bind(&L);
 }
 
 
-void MacroAssembler::Abort(const char* msg) {
+void MacroAssembler::Abort(BailoutReason reason) {
   Label abort_start;
   bind(&abort_start);
   // We want to pass the msg string like a smi to avoid GC
@@ -2827,6 +2827,7 @@ void MacroAssembler::Abort(const char* msg) {
   // 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());
@@ -2969,7 +2970,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
     b(&ok);
     bind(&fail);
-    Abort("Global functions must have initial map");
+    Abort(kGlobalFunctionsMustHaveInitialMap);
     bind(&ok);
   }
 }
@@ -3038,7 +3039,7 @@ void MacroAssembler::AssertNotSmi(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     tst(object, Operand(kSmiTagMask));
-    Check(ne, "Operand is a smi");
+    Check(ne, kOperandIsASmi);
   }
 }
 
@@ -3047,7 +3048,7 @@ void MacroAssembler::AssertSmi(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     tst(object, Operand(kSmiTagMask));
-    Check(eq, "Operand is not smi");
+    Check(eq, kOperandIsNotSmi);
   }
 }
 
@@ -3056,12 +3057,12 @@ void MacroAssembler::AssertString(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     tst(object, Operand(kSmiTagMask));
-    Check(ne, "Operand is a smi and not a string");
+    Check(ne, kOperandIsASmiAndNotAString);
     push(object);
     ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
     CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
     pop(object);
-    Check(lo, "Operand is not a string");
+    Check(lo, kOperandIsNotAString);
   }
 }
 
@@ -3070,12 +3071,12 @@ void MacroAssembler::AssertName(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     tst(object, Operand(kSmiTagMask));
-    Check(ne, "Operand is a smi and not a name");
+    Check(ne, kOperandIsASmiAndNotAName);
     push(object);
     ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
     CompareInstanceType(object, object, LAST_NAME_TYPE);
     pop(object);
-    Check(le, "Operand is not a name");
+    Check(le, kOperandIsNotAName);
   }
 }
 
@@ -3084,7 +3085,7 @@ void MacroAssembler::AssertName(Register object) {
 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
   if (emit_debug_code()) {
     CompareRoot(reg, index);
-    Check(eq, "HeapNumberMap register clobbered.");
+    Check(eq, kHeapNumberMapRegisterClobbered);
   }
 }
 
@@ -3230,7 +3231,7 @@ void MacroAssembler::CopyBytes(Register src,
   bind(&word_loop);
   if (emit_debug_code()) {
     tst(src, Operand(kPointerSize - 1));
-    Assert(eq, "Expecting alignment for CopyBytes");
+    Assert(eq, kExpectingAlignmentForCopyBytes);
   }
   cmp(length, Operand(kPointerSize));
   b(lt, &byte_loop);
@@ -3494,7 +3495,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, "The instruction to patch should be a load from pc.");
+    Check(eq, kTheInstructionToPatchShouldBeALoadFromPc);
     // Result was clobbered. Restore it.
     ldr(result, MemOperand(ldr_location));
   }
index 38308e5..8b9fa2b 100644 (file)
@@ -144,6 +144,8 @@ 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);
@@ -1136,14 +1138,14 @@ class MacroAssembler: public Assembler {
 
   // Calls Abort(msg) if the condition cond is not satisfied.
   // Use --debug_code to enable.
-  void Assert(Condition cond, const char* msg);
+  void Assert(Condition cond, BailoutReason reason);
   void AssertFastElements(Register elements);
 
   // Like Assert(), but always enabled.
-  void Check(Condition cond, const char* msg);
+  void Check(Condition cond, BailoutReason reason);
 
   // Print a message to stdout and abort execution.
-  void Abort(const char* msg);
+  void Abort(BailoutReason msg);
 
   // Verify restrictions about code generated in stubs.
   void set_generating_stub(bool value) { generating_stub_ = value; }
index 8f1ab47..defd734 100644 (file)
@@ -77,16 +77,15 @@ function ArrayIteratorNext() {
     return CreateIteratorResultObject(void 0, true);
   }
 
-  var elementKey = ToString(index);
   iterator[arrayIteratorNextIndexSymbol] = index + 1;
 
   if (itemKind == ARRAY_ITERATOR_KIND_VALUES)
-    return CreateIteratorResultObject(array[elementKey], false);
+    return CreateIteratorResultObject(array[index], false);
 
   if (itemKind == ARRAY_ITERATOR_KIND_ENTRIES)
-    return CreateIteratorResultObject([elementKey, array[elementKey]], false);
+    return CreateIteratorResultObject([index, array[index]], false);
 
-  return CreateIteratorResultObject(elementKey, false);
+  return CreateIteratorResultObject(index, false);
 }
 
 function ArrayEntries() {
index e0bca67..2077f87 100644 (file)
@@ -304,17 +304,6 @@ 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.
index f14156f..0812472 100644 (file)
@@ -291,7 +291,6 @@ class SmallMapList {
   }
 
   void Add(Handle<Map> handle, Zone* zone) {
-    ASSERT(!handle->is_deprecated());
     list_.Add(handle.location(), zone);
   }
 
@@ -1827,8 +1826,6 @@ 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_; }
@@ -1836,8 +1833,6 @@ 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:
index e52c26c..b5162ba 100644 (file)
 #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.)
@@ -47,12 +53,6 @@ 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
index dda5fe4..2a385aa 100644 (file)
@@ -1525,6 +1525,7 @@ bool Genesis::CompileScriptCached(Isolate* isolate,
         script_name,
         0,
         0,
+        false,
         top_context,
         extension,
         NULL,
@@ -2079,6 +2080,16 @@ bool Genesis::InstallExperimentalNatives() {
                "native array-iterator.js") == 0) {
       if (!CompileExperimentalBuiltin(isolate(), i)) return false;
     }
+    if (FLAG_harmony_strings &&
+        strcmp(ExperimentalNatives::GetScriptName(i).start(),
+               "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();
index 73a2e96..bb36c02 100644 (file)
@@ -259,8 +259,6 @@ 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)                              \
index 1feecf3..b309e2c 100644 (file)
@@ -30,8 +30,6 @@
 
 #include <string.h>
 
-#include "globals.h"
-
 #include "../include/v8stdint.h"
 extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
 
@@ -234,7 +232,7 @@ inline void CheckNonEqualsHelper(const char* file,
 
 // Use C++11 static_assert if possible, which gives error
 // messages that are easier to understand on first sight.
-#if V8_CXX_STATIC_ASSERT
+#if __cplusplus >= 201103L
 #define STATIC_CHECK(test) static_assert(test, #test)
 #else
 // This is inspired by the static assertion facility in boost.  This
@@ -256,7 +254,7 @@ template <int> class StaticAssertionHelper { };
   typedef                                                                     \
     StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
     SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
-#endif  // V8_CXX_STATIC_ASSERT
+#endif
 
 
 extern bool FLAG_enable_slow_asserts;
index 651ce0a..852f7b5 100644 (file)
@@ -41,13 +41,13 @@ static LChunk* OptimizeGraph(HGraph* graph) {
   DisallowHandleDereference no_deref;
 
   ASSERT(graph != NULL);
-  SmartArrayPointer<char> bailout_reason;
+  BailoutReason bailout_reason = kNoReason;
   if (!graph->Optimize(&bailout_reason)) {
-    FATAL(bailout_reason.is_empty() ? "unknown" : *bailout_reason);
+    FATAL(GetBailoutReason(bailout_reason));
   }
   LChunk* chunk = LChunk::NewChunk(graph);
   if (chunk == NULL) {
-    FATAL(graph->info()->bailout_reason());
+    FATAL(GetBailoutReason(graph->info()->bailout_reason()));
   }
   return chunk;
 }
@@ -136,7 +136,6 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
     isolate()->GetHTracer()->TraceCompilation(&info_);
   }
 
-  Zone* zone = this->zone();
   int param_count = descriptor_->register_param_count_;
   HEnvironment* start_environment = graph()->start_environment();
   HBasicBlock* next_block = CreateBasicBlock(start_environment);
@@ -144,15 +143,13 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
   next_block->SetJoinId(BailoutId::StubEntry());
   set_current_block(next_block);
 
-  HConstant* undefined_constant = new(zone) HConstant(
-      isolate()->factory()->undefined_value());
-  AddInstruction(undefined_constant);
+  HConstant* undefined_constant =
+      Add<HConstant>(isolate()->factory()->undefined_value());
   graph()->set_undefined_constant(undefined_constant);
 
   for (int i = 0; i < param_count; ++i) {
     HParameter* param =
-        new(zone) HParameter(i, HParameter::REGISTER_PARAMETER);
-    AddInstruction(param);
+        Add<HParameter>(i, HParameter::REGISTER_PARAMETER);
     start_environment->Bind(i, param);
     parameters_[i] = param;
   }
@@ -160,9 +157,9 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
   HInstruction* stack_parameter_count;
   if (descriptor_->stack_parameter_count_ != NULL) {
     ASSERT(descriptor_->environment_length() == (param_count + 1));
-    stack_parameter_count = new(zone) HParameter(param_count,
-                                                 HParameter::REGISTER_PARAMETER,
-                                                 Representation::Integer32());
+    stack_parameter_count = New<HParameter>(param_count,
+                                            HParameter::REGISTER_PARAMETER,
+                                            Representation::Integer32());
     stack_parameter_count->set_type(HType::Smi());
     // It's essential to bind this value to the environment in case of deopt.
     AddInstruction(stack_parameter_count);
@@ -174,7 +171,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
     arguments_length_ = graph()->GetConstant0();
   }
 
-  context_ = new(zone) HContext();
+  context_ = New<HContext>();
   AddInstruction(context_);
   start_environment->BindContext(context_);
 
@@ -191,20 +188,18 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
     if (!stack_parameter_count->IsConstant() &&
         descriptor_->hint_stack_parameter_count_ < 0) {
       HInstruction* amount = graph()->GetConstant1();
-      stack_pop_count = AddInstruction(
-          HAdd::New(zone, context_, stack_parameter_count, amount));
+      stack_pop_count = Add<HAdd>(stack_parameter_count, amount);
       stack_pop_count->ChangeRepresentation(Representation::Integer32());
       stack_pop_count->ClearFlag(HValue::kCanOverflow);
     } else {
       int count = descriptor_->hint_stack_parameter_count_;
-      stack_pop_count = AddInstruction(new(zone) HConstant(count));
+      stack_pop_count = Add<HConstant>(count);
     }
   }
 
   if (current_block() != NULL) {
-    HReturn* hreturn_instruction = new(zone) HReturn(return_value,
-                                                     context_,
-                                                     stack_pop_count);
+    HReturn* hreturn_instruction = New<HReturn>(return_value,
+                                                stack_pop_count);
     current_block()->Finish(hreturn_instruction);
     set_current_block(NULL);
   }
@@ -322,9 +317,9 @@ HValue* CodeStubGraphBuilder<ToNumberStub>::BuildCodeStub() {
   if_number.Else();
 
   // Convert the parameter to number using the builtin.
-  HValue* function = AddLoadJSBuiltin(Builtins::TO_NUMBER, context());
+  HValue* function = AddLoadJSBuiltin(Builtins::TO_NUMBER);
   Add<HPushArgument>(value);
-  Push(Add<HInvokeFunction>(context(), function, 1));
+  Push(Add<HInvokeFunction>(function, 1));
 
   if_number.End();
 
@@ -339,32 +334,30 @@ Handle<Code> ToNumberStub::GenerateCode() {
 
 template <>
 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
-  Zone* zone = this->zone();
   Factory* factory = isolate()->factory();
   HValue* undefined = graph()->GetConstantUndefined();
   AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode();
   FastCloneShallowArrayStub::Mode mode = casted_stub()->mode();
   int length = casted_stub()->length();
 
-  HInstruction* allocation_site =
-      AddInstruction(new(zone) HLoadKeyed(GetParameter(0),
-                                          GetParameter(1),
-                                          NULL,
-                                          FAST_ELEMENTS));
+  HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0),
+                                                  GetParameter(1),
+                                                  static_cast<HValue*>(NULL),
+                                                  FAST_ELEMENTS);
   IfBuilder checker(this);
-  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, undefined);
+  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
+                                                    undefined);
   checker.Then();
 
   HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo();
-  HInstruction* boilerplate = AddLoad(allocation_site, access);
+  HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access);
   if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) {
     HValue* elements = AddLoadElements(boilerplate);
 
     IfBuilder if_fixed_cow(this);
     if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map());
     if_fixed_cow.Then();
-    environment()->Push(BuildCloneShallowArray(context(),
-                                               boilerplate,
+    environment()->Push(BuildCloneShallowArray(boilerplate,
                                                allocation_site,
                                                alloc_site_mode,
                                                FAST_ELEMENTS,
@@ -374,23 +367,20 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
     IfBuilder if_fixed(this);
     if_fixed.If<HCompareMap>(elements, factory->fixed_array_map());
     if_fixed.Then();
-    environment()->Push(BuildCloneShallowArray(context(),
-                                               boilerplate,
+    environment()->Push(BuildCloneShallowArray(boilerplate,
                                                allocation_site,
                                                alloc_site_mode,
                                                FAST_ELEMENTS,
                                                length));
     if_fixed.Else();
-    environment()->Push(BuildCloneShallowArray(context(),
-                                               boilerplate,
+    environment()->Push(BuildCloneShallowArray(boilerplate,
                                                allocation_site,
                                                alloc_site_mode,
                                                FAST_DOUBLE_ELEMENTS,
                                                length));
   } else {
     ElementsKind elements_kind = casted_stub()->ComputeElementsKind();
-    environment()->Push(BuildCloneShallowArray(context(),
-                                               boilerplate,
+    environment()->Push(BuildCloneShallowArray(boilerplate,
                                                allocation_site,
                                                alloc_site_mode,
                                                elements_kind,
@@ -414,38 +404,33 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
   Zone* zone = this->zone();
   HValue* undefined = graph()->GetConstantUndefined();
 
-  HInstruction* boilerplate =
-      AddInstruction(new(zone) HLoadKeyed(GetParameter(0),
-                                          GetParameter(1),
-                                          NULL,
-                                          FAST_ELEMENTS));
+  HInstruction* boilerplate = Add<HLoadKeyed>(GetParameter(0),
+                                              GetParameter(1),
+                                              static_cast<HValue*>(NULL),
+                                              FAST_ELEMENTS);
 
   IfBuilder checker(this);
-  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, undefined);
+  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate,
+                                                    undefined);
   checker.And();
 
   int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize;
   HValue* boilerplate_size =
       AddInstruction(new(zone) HInstanceSize(boilerplate));
-  HValue* size_in_words =
-      AddInstruction(new(zone) HConstant(size >> kPointerSizeLog2));
+  HValue* size_in_words = Add<HConstant>(size >> kPointerSizeLog2);
   checker.If<HCompareNumericAndBranch>(boilerplate_size,
                                        size_in_words, Token::EQ);
   checker.Then();
 
-  HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size));
-  HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
-  if (isolate()->heap()->ShouldGloballyPretenure()) {
-    flags = static_cast<HAllocate::Flags>(
-       flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
-  }
+  HValue* size_in_bytes = Add<HConstant>(size);
 
-  HInstruction* object = AddInstruction(new(zone)
-      HAllocate(context(), size_in_bytes, HType::JSObject(), flags));
+  HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(),
+      isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE);
 
   for (int i = 0; i < size; i += kPointerSize) {
     HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
-    AddStore(object, access, AddLoad(boilerplate, access));
+    Add<HStoreNamedField>(object, access,
+                          Add<HLoadNamedField>(boilerplate, access));
   }
 
   environment()->Push(object);
@@ -463,14 +448,9 @@ Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
 
 template <>
 HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
-  Zone* zone = this->zone();
-
-  HValue* size = AddInstruction(new(zone) HConstant(AllocationSite::kSize));
-  HAllocate::Flags flags = HAllocate::DefaultFlags();
-  flags = static_cast<HAllocate::Flags>(
-      flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
-  HInstruction* object = AddInstruction(new(zone)
-      HAllocate(context(), size, HType::JSObject(), flags));
+  HValue* size = Add<HConstant>(AllocationSite::kSize);
+  HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED,
+      JS_OBJECT_TYPE);
 
   // Store the map
   Handle<Map> allocation_site_map(isolate()->heap()->allocation_site_map(),
@@ -478,14 +458,22 @@ HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
   AddStoreMapConstant(object, allocation_site_map);
 
   // Store the payload (smi elements kind)
-  HValue* initial_elements_kind = AddInstruction(new(zone) HConstant(
-      GetInitialFastElementsKind()));
+  HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind());
   Add<HStoreNamedField>(object,
                         HObjectAccess::ForAllocationSiteTransitionInfo(),
                         initial_elements_kind);
 
-  Add<HLinkObjectInList>(object, HObjectAccess::ForAllocationSiteWeakNext(),
-                         HLinkObjectInList::ALLOCATION_SITE_LIST);
+  // Link the object to the allocation site list
+  HValue* site_list = Add<HConstant>(
+      ExternalReference::allocation_sites_list_address(isolate()));
+  HValue* site = Add<HLoadNamedField>(site_list,
+                                      HObjectAccess::ForAllocationSiteList());
+  HStoreNamedField* store =
+      Add<HStoreNamedField>(object, HObjectAccess::ForAllocationSiteWeakNext(),
+                            site);
+  store->SkipWriteBarrier();
+  Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(),
+                        object);
 
   // We use a hammer (SkipWriteBarrier()) to indicate that we know the input
   // cell is really a Cell, and so no write barrier is needed.
@@ -493,7 +481,7 @@ HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
   // a cell. (perhaps with a new instruction, HAssert).
   HInstruction* cell = GetParameter(0);
   HObjectAccess access = HObjectAccess::ForCellValue();
-  HStoreNamedField* store = AddStore(cell, access, object);
+  store = Add<HStoreNamedField>(cell, access, object);
   store->SkipWriteBarrier();
   return cell;
 }
@@ -590,14 +578,14 @@ HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
     ArgumentClass argument_class) {
   HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
   if (context_mode == CONTEXT_CHECK_REQUIRED) {
-    HInstruction* array_function = BuildGetArrayFunction(context());
+    HInstruction* array_function = BuildGetArrayFunction();
     ArrayContextChecker checker(this, constructor, array_function);
   }
 
   HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell);
   // Walk through the property cell to the AllocationSite
-  HValue* alloc_site = AddInstruction(new(zone()) HLoadNamedField(property_cell,
-      HObjectAccess::ForCellValue()));
+  HValue* alloc_site = Add<HLoadNamedField>(property_cell,
+                                            HObjectAccess::ForCellValue());
   JSArrayBuilder array_builder(this, kind, alloc_site, constructor,
                                override_mode);
   HValue* result = NULL;
@@ -645,19 +633,17 @@ HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
   HValue* constant_one = graph()->GetConstant1();
   HValue* constant_zero = graph()->GetConstant0();
 
-  HInstruction* elements = AddInstruction(
-      new(zone()) HArgumentsElements(false));
+  HInstruction* elements = Add<HArgumentsElements>(false);
   HInstruction* argument = AddInstruction(
       new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero));
 
   HConstant* max_alloc_length =
-      new(zone()) HConstant(JSObject::kInitialMaxFastElementArray);
-  AddInstruction(max_alloc_length);
+      Add<HConstant>(JSObject::kInitialMaxFastElementArray);
   const int initial_capacity = JSArray::kPreallocatedArrayElements;
-  HConstant* initial_capacity_node = new(zone()) HConstant(initial_capacity);
+  HConstant* initial_capacity_node = New<HConstant>(initial_capacity);
   AddInstruction(initial_capacity_node);
 
-  HBoundsCheck* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length);
+  HInstruction* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length);
   IfBuilder if_builder(this);
   if_builder.If<HCompareNumericAndBranch>(checked_arg, constant_zero,
                                           Token::EQ);
@@ -697,12 +683,11 @@ HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
                       LoopBuilder::kPostIncrement);
   HValue* start = graph()->GetConstant0();
   HValue* key = builder.BeginBody(start, length, Token::LT);
-  HInstruction* argument_elements = AddInstruction(
-      new(zone()) HArgumentsElements(false));
+  HInstruction* argument_elements = Add<HArgumentsElements>(false);
   HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt(
       argument_elements, length, key));
 
-  AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind));
+  Add<HStoreKeyed>(elements, key, argument, kind);
   builder.EndBody();
   return new_object;
 }
@@ -817,45 +802,6 @@ 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 = AddInstruction(new(zone())
-        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(), context());
-    Add<HPushArgument>(GetParameter(0));
-    HValue* result = Add<HInvokeFunction>(context(), 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();
 
@@ -888,10 +834,9 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
   // Check that the map of the global has not changed: use a placeholder map
   // that will be replaced later with the global object's map.
   Handle<Map> placeholder_map = isolate()->factory()->meta_map();
-  AddInstruction(HCheckMaps::New(
-      receiver, placeholder_map, zone(), top_info()));
+  Add<HCheckMaps>(receiver, placeholder_map, top_info());
 
-  HValue* cell = Add<HConstant>(placeholder_cell, Representation::Tagged());
+  HValue* cell = Add<HConstant>(placeholder_cell);
   HObjectAccess access(HObjectAccess::ForCellPayload(isolate()));
   HValue* cell_contents = Add<HLoadNamedField>(cell, access);
 
@@ -906,7 +851,7 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
     // property has been deleted and that the store must be handled by the
     // runtime.
     IfBuilder builder(this);
-    HValue* hole_value = Add<HConstant>(hole, Representation::Tagged());
+    HValue* hole_value = Add<HConstant>(hole);
     builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
     builder.Then();
     builder.Deopt();
index 5f6616e..d472fa2 100644 (file)
@@ -204,71 +204,6 @@ 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.
@@ -354,29 +289,6 @@ 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;
index 84d9b02..c58acd6 100644 (file)
@@ -40,7 +40,6 @@ namespace internal {
 #define CODE_STUB_LIST_ALL_PLATFORMS(V)  \
   V(CallFunction)                        \
   V(CallConstruct)                       \
-  V(UnaryOp)                             \
   V(BinaryOp)                            \
   V(StringAdd)                           \
   V(SubString)                           \
@@ -593,73 +592,6 @@ 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.
index 63ddbbb..01537e8 100644 (file)
@@ -47,7 +47,7 @@ function SetConstructor() {
   if (%_IsConstructCall()) {
     %SetInitialize(this);
   } else {
-    return new $Set();
+    throw MakeTypeError('constructor_not_function', ['Set']);
   }
 }
 
@@ -141,7 +141,7 @@ function MapConstructor() {
   if (%_IsConstructCall()) {
     %MapInitialize(this);
   } else {
-    return new $Map();
+    throw MakeTypeError('constructor_not_function', ['Map']);
   }
 }
 
@@ -243,7 +243,7 @@ function WeakMapConstructor() {
   if (%_IsConstructCall()) {
     %WeakCollectionInitialize(this);
   } else {
-    return new $WeakMap();
+    throw MakeTypeError('constructor_not_function', ['WeakMap']);
   }
 }
 
@@ -335,7 +335,7 @@ function WeakSetConstructor() {
   if (%_IsConstructCall()) {
     %WeakCollectionInitialize(this);
   } else {
-    return new $WeakSet();
+    throw MakeTypeError('constructor_not_function', ['WeakSet']);
   }
 }
 
index 18c82e9..fffe5da 100644 (file)
@@ -144,7 +144,8 @@ bool CompilationCacheScript::HasOrigin(
     Handle<SharedFunctionInfo> function_info,
     Handle<Object> name,
     int line_offset,
-    int column_offset) {
+    int column_offset,
+    bool is_shared_cross_origin) {
   Handle<Script> script =
       Handle<Script>(Script::cast(function_info->script()), isolate());
   // If the script name isn't set, the boilerplate script should have
@@ -157,6 +158,8 @@ bool CompilationCacheScript::HasOrigin(
   if (column_offset != script->column_offset()->value()) return false;
   // Check that both names are strings. If not, no match.
   if (!name->IsString() || !script->name()->IsString()) return false;
+  // Were both scripts tagged by the embedder as being shared cross-origin?
+  if (is_shared_cross_origin != script->is_shared_cross_origin()) return false;
   // Compare the two name strings for equality.
   return String::cast(*name)->Equals(String::cast(script->name()));
 }
@@ -171,6 +174,7 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(
     Handle<Object> name,
     int line_offset,
     int column_offset,
+    bool is_shared_cross_origin,
     Handle<Context> context) {
   Object* result = NULL;
   int generation;
@@ -186,7 +190,11 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(
             Handle<SharedFunctionInfo>::cast(probe);
         // Break when we've found a suitable shared function info that
         // matches the origin.
-        if (HasOrigin(function_info, name, line_offset, column_offset)) {
+        if (HasOrigin(function_info,
+                      name,
+                      line_offset,
+                      column_offset,
+                      is_shared_cross_origin)) {
           result = *function_info;
           break;
         }
@@ -214,7 +222,11 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(
   if (result != NULL) {
     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result),
                                       isolate());
-    ASSERT(HasOrigin(shared, name, line_offset, column_offset));
+    ASSERT(HasOrigin(shared,
+                     name,
+                     line_offset,
+                     column_offset,
+                     is_shared_cross_origin));
     // If the script was found in a later generation, we promote it to
     // the first generation to let it survive longer in the cache.
     if (generation != 0) Put(source, context, shared);
@@ -391,12 +403,18 @@ Handle<SharedFunctionInfo> CompilationCache::LookupScript(
     Handle<Object> name,
     int line_offset,
     int column_offset,
+    bool is_shared_cross_origin,
     Handle<Context> context) {
   if (!IsEnabled()) {
     return Handle<SharedFunctionInfo>::null();
   }
 
-  return script_.Lookup(source, name, line_offset, column_offset, context);
+  return script_.Lookup(source,
+                        name,
+                        line_offset,
+                        column_offset,
+                        is_shared_cross_origin,
+                        context);
 }
 
 
index 7a236e8..414e09e 100644 (file)
@@ -99,6 +99,7 @@ class CompilationCacheScript : public CompilationSubCache {
                                     Handle<Object> name,
                                     int line_offset,
                                     int column_offset,
+                                    bool is_shared_cross_origin,
                                     Handle<Context> context);
   void Put(Handle<String> source,
            Handle<Context> context,
@@ -119,7 +120,8 @@ class CompilationCacheScript : public CompilationSubCache {
   bool HasOrigin(Handle<SharedFunctionInfo> function_info,
                  Handle<Object> name,
                  int line_offset,
-                 int column_offset);
+                 int column_offset,
+                 bool is_shared_cross_origin);
 
   void* script_histogram_;
   bool script_histogram_initialized_;
@@ -212,6 +214,7 @@ class CompilationCache {
                                           Handle<Object> name,
                                           int line_offset,
                                           int column_offset,
+                                          bool is_shared_cross_origin,
                                           Handle<Context> context);
 
   // Finds the shared function info for a source string for eval in a
index 4cac73f..ebd4995 100644 (file)
@@ -127,7 +127,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
     ASSERT(language_mode() == CLASSIC_MODE);
     SetLanguageMode(shared_info_->language_mode());
   }
-  set_bailout_reason("unknown");
+  set_bailout_reason(kUnknown);
 }
 
 
@@ -342,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("optimized too many times");
+    info()->set_bailout_reason(kOptimizedTooManyTimes);
     return AbortOptimization();
   }
 
@@ -356,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("too many parameters");
+    info()->set_bailout_reason(kTooManyParameters);
     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("too many parameters/locals");
+    info()->set_bailout_reason(kTooManyParametersLocals);
     return AbortOptimization();
   }
 
@@ -458,9 +458,9 @@ OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
   ASSERT(last_status() == SUCCEEDED);
   Timer t(this, &time_taken_to_optimize_);
   ASSERT(graph_ != NULL);
-  SmartArrayPointer<char> bailout_reason;
+  BailoutReason bailout_reason = kNoReason;
   if (!graph_->Optimize(&bailout_reason)) {
-    if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
+    if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason);
     return SetLastStatus(BAILED_OUT);
   } else {
     chunk_ = LChunk::NewChunk(graph_);
@@ -485,7 +485,9 @@ OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
     DisallowDeferredHandleDereference no_deferred_handle_deref;
     Handle<Code> optimized_code = chunk_->Codegen();
     if (optimized_code.is_null()) {
-      info()->set_bailout_reason("code generation failed");
+      if (info()->bailout_reason() != kNoReason) {
+        info()->set_bailout_reason(kCodeGenerationFailed);
+      }
       return AbortOptimization();
     }
     info()->SetCode(optimized_code);
@@ -667,6 +669,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
                                              Handle<Object> script_name,
                                              int line_offset,
                                              int column_offset,
+                                             bool is_shared_cross_origin,
                                              Handle<Context> context,
                                              v8::Extension* extension,
                                              ScriptDataImpl* pre_data,
@@ -689,6 +692,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
                                              script_name,
                                              line_offset,
                                              column_offset,
+                                             is_shared_cross_origin,
                                              context);
   }
 
@@ -712,6 +716,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
       script->set_line_offset(Smi::FromInt(line_offset));
       script->set_column_offset(Smi::FromInt(column_offset));
     }
+    script->set_is_shared_cross_origin(is_shared_cross_origin);
 
     script->set_data(script_data.is_null() ? HEAP->undefined_value()
                                            : *script_data);
@@ -777,7 +782,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("eval");
+      result->DisableOptimization(kEval);
 
       // If caller is strict mode, the result must be in strict mode or
       // extended mode as well, but not the other way around. Consider:
@@ -1052,13 +1057,13 @@ void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
   // the unoptimized code.
   OptimizingCompiler::Status status = optimizing_compiler->last_status();
   if (info->HasAbortedDueToDependencyChange()) {
-    info->set_bailout_reason("bailed out due to dependent map");
+    info->set_bailout_reason(kBailedOutDueToDependentMap);
     status = optimizing_compiler->AbortOptimization();
   } else if (status != OptimizingCompiler::SUCCEEDED) {
-    info->set_bailout_reason("failed/bailed out last time");
+    info->set_bailout_reason(kFailedBailedOutLastTime);
     status = optimizing_compiler->AbortOptimization();
   } else if (isolate->DebuggerHasBreakPoints()) {
-    info->set_bailout_reason("debugger is active");
+    info->set_bailout_reason(kDebuggerIsActive);
     status = optimizing_compiler->AbortOptimization();
   } else {
     status = optimizing_compiler->GenerateAndInstallCode();
index 332d575..50053e5 100644 (file)
@@ -258,8 +258,8 @@ class CompilationInfo {
     SaveHandle(&script_);
   }
 
-  const char* bailout_reason() const { return bailout_reason_; }
-  void set_bailout_reason(const char* reason) { bailout_reason_ = reason; }
+  BailoutReason bailout_reason() const { return bailout_reason_; }
+  void set_bailout_reason(BailoutReason reason) { bailout_reason_ = reason; }
 
   int prologue_offset() const {
     ASSERT_NE(kPrologueOffsetNotSet, prologue_offset_);
@@ -412,7 +412,7 @@ class CompilationInfo {
     }
   }
 
-  const char* bailout_reason_;
+  BailoutReason bailout_reason_;
 
   int prologue_offset_;
 
@@ -572,6 +572,7 @@ class Compiler : public AllStatic {
                                             Handle<Object> script_name,
                                             int line_offset,
                                             int column_offset,
+                                            bool is_shared_cross_origin,
                                             Handle<Context> context,
                                             v8::Extension* extension,
                                             ScriptDataImpl* pre_data,
index 1efe2ae..c7b66c2 100644 (file)
@@ -1406,6 +1406,14 @@ 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) {
@@ -1560,10 +1568,80 @@ 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) { return malloc(length); }
-  virtual void Free(void* data) { free(data); }
+  virtual void* Allocate(size_t length) {
+    void* result = malloc(length);
+    memset(result, 0, length);
+    return result;
+  }
+  virtual void* AllocateUninitialized(size_t length) {
+    return malloc(length);
+  }
+  virtual void Free(void* data, size_t) { free(data); }
+  // TODO(dslomov): Remove when v8:2823 is fixed.
+  virtual void Free(void* data) {
+#ifndef V8_SHARED
+    UNREACHABLE();
+#endif
+  }
 };
 
 
@@ -1590,6 +1668,13 @@ 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
index 4f04342..3b06985 100644 (file)
@@ -231,6 +231,7 @@ class ShellOptions {
      stress_deopt(false),
      interactive_shell(false),
      test_shell(false),
+     dump_heap_constants(false),
      num_isolates(1),
      isolate_sources(NULL) { }
 
@@ -254,6 +255,7 @@ class ShellOptions {
   bool stress_deopt;
   bool interactive_shell;
   bool test_shell;
+  bool dump_heap_constants;
   int num_isolates;
   SourceGroup* isolate_sources;
 };
index 04f8a7a..a349502 100644 (file)
@@ -159,7 +159,6 @@ 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())) {
@@ -786,6 +785,7 @@ bool Debug::CompileDebuggerScript(int index) {
   function_info = Compiler::Compile(source_code,
                                     script_name,
                                     0, 0,
+                                    false,
                                     context,
                                     NULL, NULL,
                                     Handle<String>::null(),
index 53b9b76..50d6f0b 100644 (file)
@@ -2426,25 +2426,19 @@ 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();
-  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;
+
+  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
+       !back_edges.Done();
+       back_edges.Next()) {
+    if (static_cast<int>(back_edges.loop_depth()) == loop_nesting_level) {
       PatchInterruptCodeAt(unoptimized_code,
-                           pc_after,
+                           back_edges.pc(),
                            interrupt_code,
                            replacement_code);
     }
-    back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
   }
+
   unoptimized_code->set_back_edges_patched_for_osr(true);
 #ifdef DEBUG
   Deoptimizer::VerifyInterruptCode(
@@ -2457,25 +2451,20 @@ 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();
-  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;
+
+  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
+       !back_edges.Done();
+       back_edges.Next()) {
+    if (static_cast<int>(back_edges.loop_depth()) <= loop_nesting_level) {
       RevertInterruptCodeAt(unoptimized_code,
-                            pc_after,
+                            back_edges.pc(),
                             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
@@ -2491,24 +2480,18 @@ void Deoptimizer::VerifyInterruptCode(Code* unoptimized_code,
                                       Code* interrupt_code,
                                       Code* replacement_code,
                                       int loop_nesting_level) {
-  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);
+  for (FullCodeGenerator::BackEdgeTableIterator back_edges(unoptimized_code);
+       !back_edges.Done();
+       back_edges.Next()) {
+    uint32_t loop_depth = back_edges.loop_depth();
     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,
-                                    pc_after,
+                                    back_edges.pc(),
                                     interrupt_code,
                                     replacement_code));
-    back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
   }
 }
 #endif  // DEBUG
diff --git a/deps/v8/src/extensions/i18n/date-format.cc b/deps/v8/src/extensions/i18n/date-format.cc
deleted file mode 100644 (file)
index 1058e37..0000000
+++ /dev/null
@@ -1,329 +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 "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
index 04e7a7c..b1d28e5 100644 (file)
@@ -235,7 +235,6 @@ 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.');
@@ -292,7 +291,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
     year: {writable: true}
   });
 
-  var formatter = NativeJSCreateDateTimeFormat(
+  var formatter = %CreateDateTimeFormat(
     requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved);
 
   if (tz !== undefined && tz !== resolved.timeZone) {
@@ -409,8 +408,6 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
  * DateTimeFormat.
  */
 function formatDate(formatter, dateValue) {
-  native function NativeJSInternalDateFormat();
-
   var dateMs;
   if (dateValue === undefined) {
     dateMs = Date.now();
@@ -422,7 +419,7 @@ function formatDate(formatter, dateValue) {
     throw new RangeError('Provided date is not in valid range.');
   }
 
-  return NativeJSInternalDateFormat(formatter.formatter, new Date(dateMs));
+  return %InternalDateFormat(formatter.formatter, new Date(dateMs));
 }
 
 
@@ -433,8 +430,7 @@ function formatDate(formatter, dateValue) {
  * Returns undefined if date string cannot be parsed.
  */
 function parseDate(formatter, value) {
-  native function NativeJSInternalDateParse();
-  return NativeJSInternalDateParse(formatter.formatter, String(value));
+  return %InternalDateParse(formatter.formatter, String(value));
 }
 
 
index ac33f1e..adaa633 100644 (file)
@@ -37,4 +37,4 @@ var CLEANUP_RE = new RegExp('');
 CLEANUP_RE.test('');
 
 return Intl;
-}());
+}())});
index 1c0a2d8..b854ce5 100644 (file)
@@ -34,7 +34,7 @@
  * Intl object is a single object that has some named properties,
  * all of which are constructors.
  */
-var Intl = (function() {
+Object.defineProperty(this, "Intl", { enumerable: false, value: (function() {
 
 'use strict';
 
index 1c77b88..b110b7d 100644 (file)
@@ -30,8 +30,6 @@
 
 #include "break-iterator.h"
 #include "collator.h"
-#include "date-format.h"
-#include "locale.h"
 #include "natives.h"
 #include "number-format.h"
 
@@ -49,26 +47,6 @@ 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);
index eac1166..8c87f07 100644 (file)
@@ -141,35 +141,37 @@ void Utils::AsciiToUChar(const char* source,
 }
 
 
-// static
-v8::Local<v8::ObjectTemplate> Utils::GetTemplate(v8::Isolate* 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));
+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));
+}
 
-  return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(
-      internal->factory()->i18n_template_one()));
+
+// static
+v8::Local<v8::ObjectTemplate> Utils::GetTemplate(v8::Isolate* isolate) {
+  return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
 }
 
 
 // static
 v8::Local<v8::ObjectTemplate> Utils::GetTemplate2(v8::Isolate* 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()));
+  return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
 }
 
+
 }  // namespace v8_i18n
index d7e9486..545082e 100644 (file)
@@ -255,8 +255,6 @@ 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);
   }
@@ -287,7 +285,7 @@ function lookupMatcher(service, requestedLocales) {
 
   // Didn't find a match, return default.
   if (DEFAULT_ICU_LOCALE === undefined) {
-    DEFAULT_ICU_LOCALE = NativeJSGetDefaultICULocale();
+    DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
   }
 
   return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
@@ -446,14 +444,12 @@ 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 = NativeJSGetLanguageTagVariants([original, resolved]);
+  var locales = %GetLanguageTagVariants([original, resolved]);
   if (locales[0].maximized !== locales[1].maximized) {
     return resolved;
   }
@@ -471,8 +467,7 @@ function getOptimalLanguageTag(original, resolved) {
  * that is supported. This is required by the spec.
  */
 function getAvailableLocalesOf(service) {
-  native function NativeJSAvailableLocalesOf();
-  var available = NativeJSAvailableLocalesOf(service);
+  var available = %AvailableLocalesOf(service);
 
   for (var i in available) {
     if (available.hasOwnProperty(i)) {
diff --git a/deps/v8/src/extensions/i18n/locale.cc b/deps/v8/src/extensions/i18n/locale.cc
deleted file mode 100644 (file)
index 6b6f9ac..0000000
+++ /dev/null
@@ -1,251 +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 "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
index ea95b87..e478327 100644 (file)
@@ -34,8 +34,6 @@
  * 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) {
@@ -52,7 +50,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 = NativeJSCanonicalizeLanguageTag(localeString);
+  var tag = %CanonicalizeLanguageTag(localeString);
   if (tag === 'invalid-tag') {
     throw new RangeError('Invalid language tag: ' + localeString);
   }
index c5a1fdd..3ca0efa 100644 (file)
@@ -1097,73 +1097,69 @@ void Factory::EnsureCanContainElements(Handle<JSArray> array,
 
 
 Handle<JSArrayBuffer> Factory::NewJSArrayBuffer() {
-  JSFunction* array_buffer_fun =
-      isolate()->context()->native_context()->array_buffer_fun();
+  Handle<JSFunction> array_buffer_fun(
+      isolate()->context()->native_context()->array_buffer_fun());
   CALL_HEAP_FUNCTION(
       isolate(),
-      isolate()->heap()->AllocateJSObject(array_buffer_fun),
+      isolate()->heap()->AllocateJSObject(*array_buffer_fun),
       JSArrayBuffer);
 }
 
 
 Handle<JSDataView> Factory::NewJSDataView() {
-  JSFunction* data_view_fun =
-      isolate()->context()->native_context()->data_view_fun();
+  Handle<JSFunction> data_view_fun(
+      isolate()->context()->native_context()->data_view_fun());
   CALL_HEAP_FUNCTION(
       isolate(),
-      isolate()->heap()->AllocateJSObject(data_view_fun),
+      isolate()->heap()->AllocateJSObject(*data_view_fun),
       JSDataView);
 }
 
 
-Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type) {
-  JSFunction* typed_array_fun;
-  Context* native_context = isolate()->context()->native_context();
+static JSFunction* GetTypedArrayFun(ExternalArrayType type,
+                                    Isolate* isolate) {
+  Context* native_context = isolate->context()->native_context();
   switch (type) {
     case kExternalUnsignedByteArray:
-      typed_array_fun = native_context->uint8_array_fun();
-      break;
+      return native_context->uint8_array_fun();
 
     case kExternalByteArray:
-      typed_array_fun = native_context->int8_array_fun();
-      break;
+      return native_context->int8_array_fun();
 
     case kExternalUnsignedShortArray:
-      typed_array_fun = native_context->uint16_array_fun();
-      break;
+      return native_context->uint16_array_fun();
 
     case kExternalShortArray:
-      typed_array_fun = native_context->int16_array_fun();
-      break;
+      return native_context->int16_array_fun();
 
     case kExternalUnsignedIntArray:
-      typed_array_fun = native_context->uint32_array_fun();
-      break;
+      return native_context->uint32_array_fun();
 
     case kExternalIntArray:
-      typed_array_fun = native_context->int32_array_fun();
-      break;
+      return native_context->int32_array_fun();
 
     case kExternalFloatArray:
-      typed_array_fun = native_context->float_array_fun();
-      break;
+      return native_context->float_array_fun();
 
     case kExternalDoubleArray:
-      typed_array_fun = native_context->double_array_fun();
-      break;
+      return native_context->double_array_fun();
 
     case kExternalPixelArray:
-      typed_array_fun = native_context->uint8c_array_fun();
-      break;
+      return native_context->uint8c_array_fun();
 
     default:
       UNREACHABLE();
-      return Handle<JSTypedArray>();
+      return NULL;
   }
+}
+
+
+Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type) {
+  Handle<JSFunction> typed_array_fun_handle(GetTypedArrayFun(type, isolate()));
 
   CALL_HEAP_FUNCTION(
       isolate(),
-      isolate()->heap()->AllocateJSObject(typed_array_fun),
+      isolate()->heap()->AllocateJSObject(*typed_array_fun_handle),
       JSTypedArray);
 }
 
index fa202f9..c68beb5 100644 (file)
@@ -173,6 +173,8 @@ DEFINE_bool(harmony_generators, false, "enable harmony generators")
 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)
@@ -183,6 +185,8 @@ DEFINE_implication(harmony, harmony_observation)
 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
@@ -263,7 +267,6 @@ DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing")
 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,
@@ -307,9 +310,6 @@ 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.")
index 61792a6..c17a9d5 100644 (file)
@@ -1521,9 +1521,9 @@ void StackHandler::Unwind(Isolate* isolate,
                           FixedArray* array,
                           int offset,
                           int previous_handler_offset) const {
-  STATIC_ASSERT(StackHandlerConstants::kSlotCount == 5);
+  STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5);
   ASSERT_LE(0, offset);
-  ASSERT_GE(array->length(), offset + 5);
+  ASSERT_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
   // Unwinding a stack handler into an array chains it in the opposite
   // direction, re-using the "next" slot as a "previous" link, so that stack
   // handlers can be later re-wound in the correct order.  Decode the "state"
@@ -1542,9 +1542,9 @@ int StackHandler::Rewind(Isolate* isolate,
                          FixedArray* array,
                          int offset,
                          Address fp) {
-  STATIC_ASSERT(StackHandlerConstants::kSlotCount == 5);
+  STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5);
   ASSERT_LE(0, offset);
-  ASSERT_GE(array->length(), offset + 5);
+  ASSERT_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
   Smi* prev_handler_offset = Smi::cast(array->get(offset));
   Code* code = Code::cast(array->get(offset + 1));
   Smi* smi_index = Smi::cast(array->get(offset + 2));
@@ -1560,7 +1560,7 @@ int StackHandler::Rewind(Isolate* isolate,
   Memory::uintptr_at(address() + StackHandlerConstants::kStateOffset) = state;
   Memory::Object_at(address() + StackHandlerConstants::kContextOffset) =
       context;
-  Memory::Address_at(address() + StackHandlerConstants::kFPOffset) = fp;
+  SetFp(address() + StackHandlerConstants::kFPOffset, fp);
 
   *isolate->handler_address() = address();
 
index 634ff8a..2bbbd98 100644 (file)
@@ -145,6 +145,7 @@ class StackHandler BASE_EMBEDDED {
 
   inline Object** context_address() const;
   inline Object** code_address() const;
+  inline void SetFp(Address slot, Address fp);
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
 };
@@ -176,7 +177,7 @@ class StandardFrameConstants : public AllStatic {
   static const int kContextOffset     = -1 * kPointerSize;
   static const int kCallerFPOffset    =  0 * kPointerSize;
   static const int kCallerPCOffset    = +1 * kFPOnStackSize;
-  static const int kCallerSPOffset    = +2 * kPCOnStackSize;
+  static const int kCallerSPOffset    =  kCallerPCOffset + 1 * kPCOnStackSize;
 };
 
 
index 6d802e9..f5539e8 100644 (file)
@@ -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.
index a9db54e..af63aed 100644 (file)
 #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 {
@@ -136,7 +139,64 @@ class FullCodeGenerator: public AstVisitor {
 #error Unsupported target architecture.
 #endif
 
-  static const int kBackEdgeEntrySize = 3 * kIntSize;
+  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);
+  };
+
 
  private:
   class Breakable;
@@ -625,8 +685,6 @@ 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);
index 88ebe31..2eae474 100644 (file)
@@ -56,7 +56,9 @@ class GlobalHandles::Node {
     NORMAL,     // Normal global handle.
     WEAK,       // Flagged as weak but not yet finalized.
     PENDING,    // Has been recognized as only reachable by weak handles.
-    NEAR_DEATH  // Callback has informed the handle is near death.
+    NEAR_DEATH,  // Callback has informed the handle is near death.
+
+    NUMBER_OF_STATES
   };
 
   // Maps handle location (slot) to the containing node.
@@ -71,6 +73,7 @@ class GlobalHandles::Node {
     STATIC_ASSERT(static_cast<int>(NodeState::kMask) ==
                   Internals::kNodeStateMask);
     STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
+    STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue);
     STATIC_ASSERT(NEAR_DEATH == Internals::kNodeStateIsNearDeathValue);
     STATIC_ASSERT(static_cast<int>(IsIndependent::kShift) ==
                   Internals::kNodeIsIndependentShift);
@@ -93,13 +96,12 @@ class GlobalHandles::Node {
   }
 #endif
 
-  void Initialize(int index, Node** first_free) {
+  void Initialize(int index, Node* first_free) {
     index_ = static_cast<uint8_t>(index);
     ASSERT(static_cast<int>(index_) == index);
     set_state(FREE);
     set_in_new_space_list(false);
-    parameter_or_next_free_.next_free = *first_free;
-    *first_free = this;
+    parameter_or_next_free_.next_free = first_free;
   }
 
   void Acquire(Object* object) {
@@ -111,7 +113,6 @@ class GlobalHandles::Node {
     set_state(NORMAL);
     parameter_or_next_free_.parameter = NULL;
     weak_reference_callback_ = NULL;
-    IncreaseBlockUses();
   }
 
   void Release() {
@@ -125,7 +126,7 @@ class GlobalHandles::Node {
     set_partially_dependent(false);
     weak_reference_callback_ = NULL;
 #endif
-    DecreaseBlockUses();
+    ReleaseFromBlock();
   }
 
   // Object slot accessors.
@@ -204,10 +205,6 @@ class GlobalHandles::Node {
   }
   void clear_partially_dependent() { set_partially_dependent(false); }
 
-  // Callback accessor.
-  // TODO(svenpanne) Re-enable or nuke later.
-  // WeakReferenceCallback callback() { return callback_; }
-
   // Callback parameter accessors.
   void set_parameter(void* parameter) {
     ASSERT(state() != FREE);
@@ -276,8 +273,7 @@ class GlobalHandles::Node {
  private:
   inline NodeBlock* FindBlock();
   inline GlobalHandles* GetGlobalHandles();
-  inline void IncreaseBlockUses();
-  inline void DecreaseBlockUses();
+  inline void ReleaseFromBlock();
 
   // Storage for object pointer.
   // Placed first to avoid offset computation.
@@ -315,163 +311,404 @@ class GlobalHandles::Node {
 };
 
 
-class GlobalHandles::NodeBlock {
+class GlobalHandles::BlockListIterator {
  public:
-  static const int kSize = 256;
+  explicit inline BlockListIterator(BlockList* anchor)
+      : anchor_(anchor), current_(anchor->next()) {
+    ASSERT(anchor->IsAnchor());
+  }
+  inline BlockList* block() const {
+    ASSERT(!done());
+    return current_;
+  }
+  inline bool done() const {
+    ASSERT_EQ(anchor_ == current_, current_->IsAnchor());
+    return anchor_ == current_;
+  }
+  inline void Advance() {
+    ASSERT(!done());
+    current_ = current_->next();
+  }
+
+ private:
+  BlockList* const anchor_;
+  BlockList* current_;
+  DISALLOW_COPY_AND_ASSIGN(BlockListIterator);
+};
+
+
+GlobalHandles::BlockList::BlockList()
+    : prev_block_(this),
+      next_block_(this),
+      first_free_(NULL),
+      used_nodes_(0) {}
+
+
+void GlobalHandles::BlockList::InsertAsNext(BlockList* const block) {
+  ASSERT(block != this);
+  ASSERT(!block->IsAnchor());
+  ASSERT(block->IsDetached());
+  block->prev_block_ = this;
+  block->next_block_ = next_block_;
+  next_block_->prev_block_ = block;
+  next_block_ = block;
+  ASSERT(!IsDetached());
+  ASSERT(!block->IsDetached());
+}
+
+
+void GlobalHandles::BlockList::Detach() {
+  ASSERT(!IsAnchor());
+  ASSERT(!IsDetached());
+  prev_block_->next_block_ = next_block_;
+  next_block_->prev_block_ = prev_block_;
+  prev_block_ = this;
+  next_block_ = this;
+  ASSERT(IsDetached());
+}
 
-  explicit NodeBlock(GlobalHandles* global_handles, NodeBlock* next)
-      : next_(next),
-        used_nodes_(0),
-        next_used_(NULL),
-        prev_used_(NULL),
-        global_handles_(global_handles) {}
 
-  void PutNodesOnFreeList(Node** first_free) {
+bool GlobalHandles::BlockList::HasAtLeastLength(int length) {
+  ASSERT(IsAnchor());
+  ASSERT(length > 0);
+  for (BlockListIterator it(this); !it.done(); it.Advance()) {
+    if (--length <= 0) return true;
+  }
+  return false;
+}
+
+
+#ifdef DEBUG
+int GlobalHandles::BlockList::LengthOfFreeList() {
+  int count = 0;
+  Node* node = first_free_;
+  while (node != NULL) {
+    count++;
+    node = node->next_free();
+  }
+  return count;
+}
+#endif
+
+
+int GlobalHandles::BlockList::CompareBlocks(const void* a, const void* b) {
+  const BlockList* block_a =
+      *reinterpret_cast<const BlockList**>(reinterpret_cast<uintptr_t>(a));
+  const BlockList* block_b =
+      *reinterpret_cast<const BlockList**>(reinterpret_cast<uintptr_t>(b));
+  if (block_a->used_nodes() > block_b->used_nodes()) return -1;
+  if (block_a->used_nodes() == block_b->used_nodes()) return 0;
+  return 1;
+}
+
+
+class GlobalHandles::NodeBlock : public BlockList {
+ public:
+  static const int kSize = 256;
+
+  explicit NodeBlock(GlobalHandles* global_handles)
+      : global_handles_(global_handles) {
+    // Initialize nodes
+    Node* first_free = first_free_;
     for (int i = kSize - 1; i >= 0; --i) {
       nodes_[i].Initialize(i, first_free);
+      first_free = &nodes_[i];
     }
+    first_free_ = first_free;
+    ASSERT(!IsAnchor());
+    // Link into global_handles
+    ASSERT(global_handles->non_full_blocks_.IsDetached());
+    global_handles->non_full_blocks_.InsertAsHead(this);
+    global_handles->number_of_blocks_++;
   }
 
-  Node* node_at(int index) {
-    ASSERT(0 <= index && index < kSize);
-    return &nodes_[index];
-  }
-
-  void IncreaseUses() {
+  Node* Acquire(Object* o) {
     ASSERT(used_nodes_ < kSize);
-    if (used_nodes_++ == 0) {
-      NodeBlock* old_first = global_handles_->first_used_block_;
-      global_handles_->first_used_block_ = this;
-      next_used_ = old_first;
-      prev_used_ = NULL;
-      if (old_first == NULL) return;
-      old_first->prev_used_ = this;
+    ASSERT(first_free_ != NULL);
+    ASSERT(global_handles_->non_full_blocks_.next() == this);
+    // Remove from free list
+    Node* node = first_free_;
+    first_free_ = node->next_free();
+    // Increment counters
+    global_handles_->isolate()->counters()->global_handles()->Increment();
+    global_handles_->number_of_global_handles_++;
+    // Initialize node with value
+    node->Acquire(o);
+    bool now_full = ++used_nodes_ == kSize;
+    ASSERT_EQ(now_full, first_free_ == NULL);
+    if (now_full) {
+      // Move block to tail of non_full_blocks_
+      Detach();
+      global_handles_->full_blocks_.InsertAsTail(this);
     }
+    return node;
   }
 
-  void DecreaseUses() {
+  void Release(Node* node) {
     ASSERT(used_nodes_ > 0);
-    if (--used_nodes_ == 0) {
-      if (next_used_ != NULL) next_used_->prev_used_ = prev_used_;
-      if (prev_used_ != NULL) prev_used_->next_used_ = next_used_;
-      if (this == global_handles_->first_used_block_) {
-        global_handles_->first_used_block_ = next_used_;
-      }
+    // Add to free list
+    node->set_next_free(first_free_);
+    first_free_ = node;
+    // Decrement counters
+    global_handles_->isolate()->counters()->global_handles()->Decrement();
+    global_handles_->number_of_global_handles_--;
+    bool was_full = used_nodes_-- == kSize;
+    ASSERT_EQ(was_full, first_free_->next_free() == NULL);
+    if (was_full) {
+      // Move this block to head of non_full_blocks_
+      Detach();
+      global_handles_->non_full_blocks_.InsertAsHead(this);
     }
   }
 
+  Node* node_at(int index) {
+    ASSERT(0 <= index && index < kSize);
+    return &nodes_[index];
+  }
+
   GlobalHandles* global_handles() { return global_handles_; }
 
-  // Next block in the list of all blocks.
-  NodeBlock* next() const { return next_; }
+  static NodeBlock* Cast(BlockList* block_list) {
+    ASSERT(!block_list->IsAnchor());
+    return static_cast<NodeBlock*>(block_list);
+  }
 
-  // Next/previous block in the list of blocks with used nodes.
-  NodeBlock* next_used() const { return next_used_; }
-  NodeBlock* prev_used() const { return prev_used_; }
+  static NodeBlock* From(Node* node, uint8_t index) {
+    uintptr_t ptr = reinterpret_cast<uintptr_t>(node - index);
+    ptr -= OFFSET_OF(NodeBlock, nodes_);
+    NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr);
+    ASSERT(block->node_at(index) == node);
+    return block;
+  }
 
  private:
   Node nodes_[kSize];
-  NodeBlock* const next_;
-  int used_nodes_;
-  NodeBlock* next_used_;
-  NodeBlock* prev_used_;
   GlobalHandles* global_handles_;
 };
 
 
-GlobalHandles* GlobalHandles::Node::GetGlobalHandles() {
-  return FindBlock()->global_handles();
+void GlobalHandles::BlockList::SortBlocks(GlobalHandles* global_handles,
+                                          bool prune) {
+  // Always sort at least 2 blocks
+  if (!global_handles->non_full_blocks_.HasAtLeastLength(2)) return;
+  // build a vector that could contain the upper bound of the block count
+  int number_of_blocks = global_handles->block_count();
+  // Build array of blocks and update number_of_blocks to actual count
+  ScopedVector<BlockList*> blocks(number_of_blocks);
+  {
+    int i = 0;
+    BlockList* anchor = &global_handles->non_full_blocks_;
+    for (BlockListIterator it(anchor); !it.done(); it.Advance()) {
+      blocks[i++] = it.block();
+    }
+    number_of_blocks = i;
+  }
+  // Nothing to do.
+  if (number_of_blocks <= 1) return;
+  // Sort blocks
+  qsort(blocks.start(), number_of_blocks, sizeof(blocks[0]), CompareBlocks);
+  // Prune empties
+  if (prune) {
+    static const double kUnusedPercentage = 0.30;
+    static const double kUsedPercentage = 1.30;
+    int total_slots = global_handles->number_of_blocks_ * NodeBlock::kSize;
+    const int total_used = global_handles->number_of_global_handles_;
+    const int target_unused = static_cast<int>(Max(
+        total_used * kUsedPercentage,
+        total_slots * kUnusedPercentage));
+    // Reverse through empty blocks. Note: always leave one block free.
+    int blocks_deleted = 0;
+    for (int i = number_of_blocks - 1; i > 0 && blocks[i]->IsUnused(); i--) {
+      // Not worth deleting
+      if (total_slots - total_used < target_unused) break;
+      blocks[i]->Detach();
+      delete blocks[i];
+      blocks_deleted++;
+      total_slots -= NodeBlock::kSize;
+    }
+    global_handles->number_of_blocks_ -= blocks_deleted;
+    number_of_blocks -= blocks_deleted;
+  }
+  // Relink all blocks
+  for (int i = 0; i < number_of_blocks; i++) {
+    blocks[i]->Detach();
+    global_handles->non_full_blocks_.InsertAsTail(blocks[i]);
+  }
+#ifdef DEBUG
+  // Check sorting
+  BlockList* anchor = &global_handles->non_full_blocks_;
+  int last_size = NodeBlock::kSize;
+  for (BlockListIterator it(anchor); !it.done(); it.Advance()) {
+    ASSERT(it.block()->used_nodes() <= last_size);
+    last_size = it.block()->used_nodes();
+  }
+#endif
 }
 
 
-GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
-  intptr_t ptr = reinterpret_cast<intptr_t>(this);
-  ptr = ptr - index_ * sizeof(Node);
-  NodeBlock* block = reinterpret_cast<NodeBlock*>(ptr);
-  ASSERT(block->node_at(index_) == this);
-  return block;
+#ifdef DEBUG
+void GlobalHandles::VerifyBlockInvariants() {
+  int number_of_blocks = 0;
+  int number_of_handles = 0;
+  for (int i = 0; i < kAllAnchorsSize; i++) {
+    for (BlockListIterator it(all_anchors_[i]); !it.done(); it.Advance()) {
+      BlockList* block = it.block();
+      number_of_blocks++;
+      int used_nodes = block->used_nodes();
+      number_of_handles += used_nodes;
+      int unused_nodes = block->LengthOfFreeList();
+      ASSERT_EQ(used_nodes + unused_nodes, NodeBlock::kSize);
+      if (all_anchors_[i] == &full_blocks_) {
+        ASSERT_EQ(NodeBlock::kSize, used_nodes);
+      } else {
+        ASSERT_NE(NodeBlock::kSize, used_nodes);
+      }
+    }
+  }
+  ASSERT_EQ(number_of_handles, number_of_global_handles_);
+  ASSERT_EQ(number_of_blocks, number_of_blocks_);
 }
+#endif
 
 
-void GlobalHandles::Node::IncreaseBlockUses() {
-  NodeBlock* node_block = FindBlock();
-  node_block->IncreaseUses();
-  GlobalHandles* global_handles = node_block->global_handles();
-  global_handles->isolate()->counters()->global_handles()->Increment();
-  global_handles->number_of_global_handles_++;
+void GlobalHandles::SortBlocks(bool shouldPrune) {
+#ifdef DEBUG
+  VerifyBlockInvariants();
+#endif
+  BlockList::SortBlocks(this, shouldPrune);
+#ifdef DEBUG
+  VerifyBlockInvariants();
+#endif
 }
 
 
-void GlobalHandles::Node::DecreaseBlockUses() {
-  NodeBlock* node_block = FindBlock();
-  GlobalHandles* global_handles = node_block->global_handles();
-  parameter_or_next_free_.next_free = global_handles->first_free_;
-  global_handles->first_free_ = this;
-  node_block->DecreaseUses();
-  global_handles->isolate()->counters()->global_handles()->Decrement();
-  global_handles->number_of_global_handles_--;
+GlobalHandles* GlobalHandles::Node::GetGlobalHandles() {
+  return FindBlock()->global_handles();
+}
+
+
+GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
+  return NodeBlock::From(this, index_);
+}
+
+
+void GlobalHandles::Node::ReleaseFromBlock() {
+  FindBlock()->Release(this);
 }
 
 
 class GlobalHandles::NodeIterator {
  public:
   explicit NodeIterator(GlobalHandles* global_handles)
-      : block_(global_handles->first_used_block_),
-        index_(0) {}
+      : all_anchors_(global_handles->all_anchors_),
+        block_(all_anchors_[0]),
+        anchor_index_(0),
+        node_index_(0) {
+    AdvanceBlock();
+  }
 
-  bool done() const { return block_ == NULL; }
+  bool done() const {
+    return anchor_index_ == kAllAnchorsSize;
+  }
 
   Node* node() const {
     ASSERT(!done());
-    return block_->node_at(index_);
+    return NodeBlock::Cast(block_)->node_at(node_index_);
   }
 
   void Advance() {
     ASSERT(!done());
-    if (++index_ < NodeBlock::kSize) return;
-    index_ = 0;
-    block_ = block_->next_used();
+    if (++node_index_ < NodeBlock::kSize) return;
+    node_index_ = 0;
+    AdvanceBlock();
   }
 
+  typedef int CountArray[Node::NUMBER_OF_STATES];
+  static int CollectStats(GlobalHandles* global_handles, CountArray counts);
+
  private:
-  NodeBlock* block_;
-  int index_;
+  void AdvanceBlock() {
+    ASSERT(!done());
+    while (true) {
+      block_ = block_->next();
+      // block is valid
+      if (block_ != all_anchors_[anchor_index_]) {
+        ASSERT(!done());
+        ASSERT(!block_->IsAnchor());
+        // skip empty blocks
+        if (block_->IsUnused()) continue;
+        return;
+      }
+      // jump lists
+      anchor_index_++;
+      if (anchor_index_ == kAllAnchorsSize) break;
+      block_ = all_anchors_[anchor_index_];
+    }
+    ASSERT(done());
+  }
+
+  BlockList* const * const all_anchors_;
+  BlockList* block_;
+  int anchor_index_;
+  int node_index_;
 
   DISALLOW_COPY_AND_ASSIGN(NodeIterator);
 };
 
 
+int GlobalHandles::NodeIterator::CollectStats(GlobalHandles* global_handles,
+                                              CountArray counts) {
+  static const int kSize = Node::NUMBER_OF_STATES;
+  for (int i = 0; i < kSize; i++) {
+    counts[i] = 0;
+  }
+  int total = 0;
+  for (NodeIterator it(global_handles); !it.done(); it.Advance()) {
+    total++;
+    Node::State state = it.node()->state();
+    ASSERT(state >= 0 && state < kSize);
+    counts[state]++;
+  }
+  // NodeIterator skips empty blocks
+  int skipped = global_handles->number_of_blocks_ * NodeBlock::kSize - total;
+  total += skipped;
+  counts[Node::FREE] += total;
+  return total;
+}
+
+
 GlobalHandles::GlobalHandles(Isolate* isolate)
     : isolate_(isolate),
+      number_of_blocks_(0),
       number_of_global_handles_(0),
-      first_block_(NULL),
-      first_used_block_(NULL),
-      first_free_(NULL),
       post_gc_processing_count_(0),
-      object_group_connections_(kObjectGroupConnectionsCapacity) {}
+      object_group_connections_(kObjectGroupConnectionsCapacity) {
+  all_anchors_[0] = &full_blocks_;
+  all_anchors_[1] = &non_full_blocks_;
+}
 
 
 GlobalHandles::~GlobalHandles() {
-  NodeBlock* block = first_block_;
-  while (block != NULL) {
-    NodeBlock* tmp = block->next();
-    delete block;
-    block = tmp;
+  for (int i = 0; i < kAllAnchorsSize; i++) {
+    BlockList* block = all_anchors_[i]->next();
+    while (block != all_anchors_[i]) {
+      BlockList* tmp = block->next();
+      block->Detach();
+      delete NodeBlock::Cast(block);
+      block = tmp;
+    }
   }
-  first_block_ = NULL;
 }
 
 
 Handle<Object> GlobalHandles::Create(Object* value) {
-  if (first_free_ == NULL) {
-    first_block_ = new NodeBlock(this, first_block_);
-    first_block_->PutNodesOnFreeList(&first_free_);
-  }
-  ASSERT(first_free_ != NULL);
-  // Take the first node in the free list.
-  Node* result = first_free_;
-  first_free_ = result->next_free();
-  result->Acquire(value);
+  if (non_full_blocks_.IsDetached()) {
+    new NodeBlock(this);
+    ASSERT(!non_full_blocks_.IsDetached());
+  }
+  ASSERT(non_full_blocks_.IsAnchor());
+  ASSERT(!non_full_blocks_.next()->IsAnchor());
+  Node* result = NodeBlock::Cast(non_full_blocks_.next())->Acquire(value);
   if (isolate_->heap()->InNewSpace(value) &&
       !result->is_in_new_space_list()) {
     new_space_nodes_.Add(result);
@@ -661,21 +898,32 @@ bool GlobalHandles::PostGarbageCollectionProcessing(
       }
     }
   } else {
-    for (NodeIterator it(this); !it.done(); it.Advance()) {
-      if (!it.node()->IsRetainer()) {
-        // Free nodes do not have weak callbacks. Do not use them to compute
-        // the next_gc_likely_to_collect_more.
-        continue;
+    // Must cache all blocks, as NodeIterator can't survive mutation.
+    List<NodeBlock*> blocks(number_of_blocks_);
+    for (int i = 0; i < kAllAnchorsSize; i++) {
+      for (BlockListIterator it(all_anchors_[i]); !it.done(); it.Advance()) {
+        blocks.Add(NodeBlock::Cast(it.block()));
       }
-      it.node()->clear_partially_dependent();
-      if (it.node()->PostGarbageCollectionProcessing(isolate_)) {
-        if (initial_post_gc_processing_count != post_gc_processing_count_) {
-          // See the comment above.
-          return next_gc_likely_to_collect_more;
+    }
+    for (int block_index = 0; block_index < blocks.length(); block_index++) {
+      NodeBlock* block = blocks[block_index];
+      for (int node_index = 0; node_index < NodeBlock::kSize; node_index++) {
+        Node* node = block->node_at(node_index);
+        if (!node->IsRetainer()) {
+          // Free nodes do not have weak callbacks. Do not use them to compute
+          // the next_gc_likely_to_collect_more.
+          continue;
+        }
+        node->clear_partially_dependent();
+        if (node->PostGarbageCollectionProcessing(isolate_)) {
+          if (initial_post_gc_processing_count != post_gc_processing_count_) {
+            // See the comment above.
+            return next_gc_likely_to_collect_more;
+          }
+        }
+        if (!node->IsRetainer()) {
+          next_gc_likely_to_collect_more = true;
         }
-      }
-      if (!it.node()->IsRetainer()) {
-        next_gc_likely_to_collect_more = true;
       }
     }
   }
@@ -698,6 +946,8 @@ bool GlobalHandles::PostGarbageCollectionProcessing(
     }
   }
   new_space_nodes_.Rewind(last);
+  bool shouldPruneBlocks = collector != SCAVENGER;
+  SortBlocks(shouldPruneBlocks);
   return next_gc_likely_to_collect_more;
 }
 
@@ -765,48 +1015,30 @@ int GlobalHandles::NumberOfGlobalObjectWeakHandles() {
 
 
 void GlobalHandles::RecordStats(HeapStats* stats) {
-  *stats->global_handle_count = 0;
-  *stats->weak_global_handle_count = 0;
-  *stats->pending_global_handle_count = 0;
-  *stats->near_death_global_handle_count = 0;
-  *stats->free_global_handle_count = 0;
-  for (NodeIterator it(this); !it.done(); it.Advance()) {
-    *stats->global_handle_count += 1;
-    if (it.node()->state() == Node::WEAK) {
-      *stats->weak_global_handle_count += 1;
-    } else if (it.node()->state() == Node::PENDING) {
-      *stats->pending_global_handle_count += 1;
-    } else if (it.node()->state() == Node::NEAR_DEATH) {
-      *stats->near_death_global_handle_count += 1;
-    } else if (it.node()->state() == Node::FREE) {
-      *stats->free_global_handle_count += 1;
-    }
-  }
+  NodeIterator::CountArray counts;
+  int total = NodeIterator::CollectStats(this, counts);
+  *stats->global_handle_count = total;
+  *stats->weak_global_handle_count = counts[Node::WEAK];
+  *stats->pending_global_handle_count = counts[Node::PENDING];
+  *stats->near_death_global_handle_count = counts[Node::NEAR_DEATH];
+  *stats->free_global_handle_count = counts[Node::FREE];
 }
 
+
 #ifdef DEBUG
 
 void GlobalHandles::PrintStats() {
-  int total = 0;
-  int weak = 0;
-  int pending = 0;
-  int near_death = 0;
-  int destroyed = 0;
-
-  for (NodeIterator it(this); !it.done(); it.Advance()) {
-    total++;
-    if (it.node()->state() == Node::WEAK) weak++;
-    if (it.node()->state() == Node::PENDING) pending++;
-    if (it.node()->state() == Node::NEAR_DEATH) near_death++;
-    if (it.node()->state() == Node::FREE) destroyed++;
-  }
-
+  NodeIterator::CountArray counts;
+  int total = NodeIterator::CollectStats(this, counts);
+  size_t total_consumed = sizeof(NodeBlock) * number_of_blocks_;
   PrintF("Global Handle Statistics:\n");
-  PrintF("  allocated memory = %" V8_PTR_PREFIX "dB\n", sizeof(Node) * total);
-  PrintF("  # weak       = %d\n", weak);
-  PrintF("  # pending    = %d\n", pending);
-  PrintF("  # near_death = %d\n", near_death);
-  PrintF("  # free       = %d\n", destroyed);
+  PrintF("  allocated blocks = %d\n", number_of_blocks_);
+  PrintF("  allocated memory = %" V8_PTR_PREFIX "dB\n", total_consumed);
+  PrintF("  # normal     = %d\n", counts[Node::NORMAL]);
+  PrintF("  # weak       = %d\n", counts[Node::WEAK]);
+  PrintF("  # pending    = %d\n", counts[Node::PENDING]);
+  PrintF("  # near_death = %d\n", counts[Node::NEAR_DEATH]);
+  PrintF("  # free       = %d\n", counts[Node::FREE]);
   PrintF("  # total      = %d\n", total);
 }
 
@@ -1018,4 +1250,68 @@ 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
index cd75133..2c20711 100644 (file)
@@ -31,6 +31,7 @@
 #include "../include/v8.h"
 #include "../include/v8-profiler.h"
 
+#include "handles.h"
 #include "list.h"
 #include "v8utils.h"
 
@@ -156,6 +157,9 @@ class GlobalHandles {
     return number_of_global_handles_;
   }
 
+  // Returns the current number of allocated blocks
+  int block_count() const { return number_of_blocks_; }
+
   // Clear the weakness of a global handle.
   static void ClearWeakness(Object** location);
 
@@ -275,11 +279,14 @@ class GlobalHandles {
 #ifdef DEBUG
   void PrintStats();
   void Print();
+  void VerifyBlockInvariants();
 #endif
 
  private:
   explicit GlobalHandles(Isolate* isolate);
 
+  void SortBlocks(bool shouldPrune);
+
   // Migrates data from the internal representation (object_group_connections_,
   // retainer_infos_ and implicit_ref_connections_) to the public and more
   // efficient representation (object_groups_ and implicit_ref_groups_).
@@ -293,20 +300,64 @@ class GlobalHandles {
   class Node;
   class NodeBlock;
   class NodeIterator;
+  class BlockListIterator;
+  // Base class for NodeBlock
+  class BlockList {
+   public:
+    BlockList();
+    ~BlockList() { ASSERT(IsDetached()); }
+    void Detach();
+    void InsertAsHead(BlockList* block) {
+      ASSERT(IsAnchor());
+      InsertAsNext(block);
+    }
+    void InsertAsTail(BlockList* block) {
+      ASSERT(IsAnchor());
+      prev_block_->InsertAsNext(block);
+    }
+    inline bool IsAnchor() { return first_free_ == NULL && used_nodes_ == 0; }
+    inline bool IsDetached() {
+      ASSERT_EQ(prev_block_ == this, next_block_ == this);
+      return prev_block_ == this;
+    }
+    bool HasAtLeastLength(int length);
+    bool IsUnused() { return used_nodes_ == 0; }
+    int used_nodes() const { return used_nodes_; }
+    BlockList* next() { return next_block_; }
+    BlockList* prev() { return prev_block_; }
+#ifdef DEBUG
+    int LengthOfFreeList();
+#endif
+    static void SortBlocks(GlobalHandles* global_handles, bool prune);
+
+   protected:
+    BlockList* prev_block_;
+    BlockList* next_block_;
+    Node* first_free_;
+    int used_nodes_;
+
+   private:
+    // Needed for quicksort
+    static int CompareBlocks(const void* a, const void* b);
+    void InsertAsNext(BlockList* block);
+    DISALLOW_COPY_AND_ASSIGN(BlockList);
+  };
 
   Isolate* isolate_;
 
+  // Field always containing the number of blocks allocated.
+  int number_of_blocks_;
   // Field always containing the number of handles to global objects.
   int number_of_global_handles_;
 
-  // List of all allocated node blocks.
-  NodeBlock* first_block_;
+  // Anchors for doubly linked lists of blocks
+  BlockList full_blocks_;
+  BlockList non_full_blocks_;
 
-  // List of node blocks with used nodes.
-  NodeBlock* first_used_block_;
-
-  // Free list of nodes.
-  Node* first_free_;
+  // An array of all the anchors held by GlobalHandles.
+  // This simplifies iteration across all blocks.
+  static const int kAllAnchorsSize = 2;
+  BlockList*  all_anchors_[kAllAnchorsSize];
 
   // Contains all nodes holding new space objects. Note: when the list
   // is accessed, some of the objects may have been promoted already.
@@ -331,6 +382,76 @@ 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_
index 627c951..26fd531 100644 (file)
 #ifndef V8_GLOBALS_H_
 #define V8_GLOBALS_H_
 
-// ----------------------------------------------------------------------------
-// Operating system detection (V8_OS_x)
-//
-//  ANDROID - Android
-//  BSD4    - Any BSD 4.4 system
-//  CYGWIN  - Cygwin
-//  DARWIN  - Darwin / Mac OS X
-//  FREEBSD - FreeBSD
-//  LINUX   - Linux
-//  NACL    - Native Client
-//  NETBSD  - NetBSD
-//  OPENBSD - OpenBSD
-//  SOLARIS - Solaris
-//  UNIX    - Any UNIX BSD/SYSV system
-//  WIN32   - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
-
-#if defined(ANDROID) || defined(__ANDROID__)
-# define V8_OS_ANDROID 1
-# define V8_OS_LINUX 1
-# define V8_OS_UNIX 1
-#elif defined(__APPLE__) && defined(__MACH__)
-# define V8_OS_DARWIN 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#elif defined(__CYGWIN__)
-# define V8_OS_CYGWIN 1
-# define V8_OS_UNIX 1
-#elif defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
-# define V8_OS_WIN32 1
-# define V8_OS_WIN64 1
-#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \
-    (defined(__MWERKS__) && defined(__INTEL__))
-# define V8_OS_WIN32 1
-#elif defined(__sun) || defined(sun)
-# define V8_OS_SOLARIS 1
-# define V8_OS_UNIX 1
-#elif defined(__native_client__)
-# define V8_OS_NACL 1
-#elif defined(__linux__) || defined(__linux)
-# define V8_OS_LINUX 1
-# define V8_OS_UNIX 1
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
-# define V8_OS_FREEBSD 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#elif defined(__NetBSD__)
-# define V8_OS_NETBSD 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#elif defined(__OpenBSD__)
-# define V8_OS_OPENBSD 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#else
-# error Operating system was not detected as supported by v8
-#endif
+// Define V8_INFINITY
+#define V8_INFINITY INFINITY
 
+// GCC specific stuff
+#ifdef __GNUC__
 
-// ----------------------------------------------------------------------------
-// Compiler detection (V8_CC_x)
-//
-//  CLANG - C++ front-end for the LLVM compiler
-//  GNU   - GNU C++ or compatible
-//  INTEL - Intel C++ for Linux or Windows
-//  MINGW - Minimalistic GNU for Windows Compiler
-//  MIPS  - MIPSpro C++
-//  MSVC  - Microsoft Visual C/C++ or compatible
-//  RVCT  - ARM Realview Compiler Suite
+#define __GNUC_VERSION_FOR_INFTY__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
 
-#if defined(_MSC_VER)
-# define V8_CC_MSVC 1
-# if defined(__INTEL_COMPILER)
-#  define V8_CC_INTEL 1
-# endif
-#elif defined(__GNUC__)
-# define V8_CC_GNU 1
-# if defined(__MINGW64__)
-#  define V8_CC_MINGW 1
-#  define V8_CC_MINGW64 1
-# elif defined(__MINGW32__)
-#  define V8_CC_MINGW 1
-#  define V8_CC_MINGW32 1
-# elif defined(__ARMCC__) || defined(__CC_ARM)
-#  define V8_CC_RVCT 1  // ARM Realview Compiler Suite also masquerades as GCC
-# elif defined(__INTEL_COMPILER)
-#  define V8_CC_INTEL 1  // Intel C++ also masquerades as GCC 3.2.0
-# elif defined(__clang__)
-#  define V8_CC_CLANG 1  // Clang also masquerades as GCC 4.2.1
-# endif
-#elif defined(__ARMCC__) || defined(__CC_ARM)
-# define V8_CC_RVCT 1
-#elif defined(__INTEL_COMPILER)
-# define V8_CC_INTEL 1
-#elif defined(__SUNPRO_CC) || defined(__SUNPRO_C)
-# define V8_CC_SUN 1
-#else
-# error Compiler was not detected as supported by v8
+// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
+// warning flag and certain versions of GCC due to a bug:
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
+// For now, we use the more involved template-based version from <limits>, but
+// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
+// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
+#if __GNUC_VERSION_FOR_INFTY__ >= 29600 && __GNUC_VERSION_FOR_INFTY__ < 40100
+#include <limits>
+#undef V8_INFINITY
+#define V8_INFINITY std::numeric_limits<double>::infinity()
 #endif
+#undef __GNUC_VERSION_FOR_INFTY__
 
-#if V8_CC_GNU
-# define V8_GNUC_PREREQ(major, minor) \
-    (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
-#else
-# define V8_GNUC_PREREQ(major, minor) 0
-#endif  // V8_CC_GNU
-
-
-// ----------------------------------------------------------------------------
-// Compiler features
+#endif  // __GNUC__
 
-// C++11 deleted functions
-#if __cplusplus >= 201103L
-# define V8_CXX_DELETED_FUNCTIONS 1
-#elif V8_CC_CLANG
-# define V8_CXX_DELETED_FUNCTIONS __has_feature(cxx_deleted_functions)
-#else
-# define V8_CXX_DELETED_FUNCTIONS (defined(__GXX_EXPERIMENTAL_CXX0X__) && \
-                                   V8_GNUC_PREREQ(4, 4))
+#ifdef _MSC_VER
+#undef V8_INFINITY
+#define V8_INFINITY HUGE_VAL
 #endif
 
-// C++11 static_assert()
-#if __cplusplus >= 201103L
-# define V8_CXX_STATIC_ASSERT 1
-#elif V8_CC_CLANG
-# define V8_CXX_STATIC_ASSERT (__has_extension(cxx_static_assert) || \
-                               __has_feature(cxx_static_assert))
-#else
-# define V8_CXX_STATIC_ASSERT (defined(__GXX_EXPERIMENTAL_CXX0X__) && \
-                               V8_GNUC_PREREQ(4, 3))
-#endif
 
+#include "../include/v8stdint.h"
+
+namespace v8 {
+namespace internal {
 
-// ----------------------------------------------------------------------------
-// Host architecture detection.  For more info on what's defined, see:
+// Processor architecture detection.  For more info on what's defined, see:
 //   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
 //   http://www.agner.org/optimize/calling_conventions.pdf
 //   or with gcc, run: "echo | gcc -E -dM -"
-
 #if defined(_M_X64) || defined(__x86_64__)
-# if V8_OS_NACL
+#if defined(__native_client__)
 // For Native Client builds of V8, use V8_TARGET_ARCH_ARM, so that V8
 // generates ARM machine code, together with a portable ARM simulator
 // compiled for the host architecture in question.
 //
 // Since Native Client is ILP-32 on all architectures we use
 // V8_HOST_ARCH_IA32 on both 32- and 64-bit x86.
-#  define V8_HOST_ARCH_IA32 1
-#  define V8_HOST_ARCH_32_BIT 1
-#  define V8_HOST_CAN_READ_UNALIGNED 1
-# else
-#  define V8_HOST_ARCH_X64 1
-#  define V8_HOST_ARCH_64_BIT 1
-#  define V8_HOST_CAN_READ_UNALIGNED 1
-# endif  // V8_OS_NACL
+#define V8_HOST_ARCH_IA32 1
+#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#else
+#define V8_HOST_ARCH_X64 1
+#define V8_HOST_ARCH_64_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#endif  // __native_client__
 #elif defined(_M_IX86) || defined(__i386__)
-# define V8_HOST_ARCH_IA32 1
-# define V8_HOST_ARCH_32_BIT 1
-# define V8_HOST_CAN_READ_UNALIGNED 1
+#define V8_HOST_ARCH_IA32 1
+#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
 #elif defined(__ARMEL__)
-# define V8_HOST_ARCH_ARM 1
-# define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_ARCH_ARM 1
+#define V8_HOST_ARCH_32_BIT 1
 #elif defined(__MIPSEL__)
-# define V8_HOST_ARCH_MIPS 1
-# define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_ARCH_MIPS 1
+#define V8_HOST_ARCH_32_BIT 1
 #else
-# error Host architecture was not detected as supported by v8
+#error Host architecture was not detected as supported by v8
 #endif
 
 #if defined(__ARM_ARCH_7A__) || \
     defined(__ARM_ARCH_7__)
 # define CAN_USE_ARMV7_INSTRUCTIONS 1
 # ifndef CAN_USE_VFP3_INSTRUCTIONS
-#  define CAN_USE_VFP3_INSTRUCTIONS 1
+#  define CAN_USE_VFP3_INSTRUCTIONS
 # endif
 #endif
 
 
-// ----------------------------------------------------------------------------
 // Target architecture detection. This may be set externally. If not, detect
 // in the same way as the host architecture, that is, target the native
 // environment as presented by the compiler.
-
 #if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && \
     !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS
-# if V8_HOST_ARCH_X64
-#  define V8_TARGET_ARCH_X64 1
-# elif V8_HOST_ARCH_IA32
-#  define V8_TARGET_ARCH_IA32 1
-# elif V8_HOST_ARCH_ARM
-#  define V8_TARGET_ARCH_ARM 1
-# elif V8_HOST_ARCH_MIPS
-#  define V8_TARGET_ARCH_MIPS 1
-# else
-#  error Target architecture was not detected as supported by v8
-# endif
+#if defined(_M_X64) || defined(__x86_64__)
+#define V8_TARGET_ARCH_X64 1
+#elif defined(_M_IX86) || defined(__i386__)
+#define V8_TARGET_ARCH_IA32 1
+#elif defined(__ARMEL__)
+#define V8_TARGET_ARCH_ARM 1
+#elif defined(__MIPSEL__)
+#define V8_TARGET_ARCH_MIPS 1
+#else
+#error Target architecture was not detected as supported by v8
+#endif
 #endif
 
 // Check for supported combinations of host and target architectures.
 #if V8_TARGET_ARCH_IA32 && !V8_HOST_ARCH_IA32
-# error Target architecture ia32 is only supported on ia32 host
-#elif V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
-# error Target architecture x64 is only supported on x64 host
-#elif V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM)
-# error Target architecture arm is only supported on arm and ia32 host
-#elif V8_TARGET_ARCH_MIPS && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_MIPS)
-# error Target architecture mips is only supported on mips and ia32 host
+#error Target architecture ia32 is only supported on ia32 host
+#endif
+#if V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
+#error Target architecture x64 is only supported on x64 host
+#endif
+#if (V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM))
+#error Target architecture arm is only supported on arm and ia32 host
+#endif
+#if (V8_TARGET_ARCH_MIPS && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_MIPS))
+#error Target architecture mips is only supported on mips and ia32 host
 #endif
 
 // Determine whether we are running in a simulated environment.
 // Setting USE_SIMULATOR explicitly from the build script will force
 // the use of a simulated environment.
 #if !defined(USE_SIMULATOR)
-# if V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM
-#  define USE_SIMULATOR 1
-# elif V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS
-#  define USE_SIMULATOR 1
-# endif
+#if (V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM)
+#define USE_SIMULATOR 1
+#endif
+#if (V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS)
+#define USE_SIMULATOR 1
 #endif
-
-// Determine architecture endiannes (we only support little-endian).
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || \
-    V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
-# define V8_TARGET_LITTLE_ENDIAN 1
-#else
-# error Unknown target architecture endiannes
 #endif
 
-
-// ----------------------------------------------------------------------------
-// Define our own macros for writing 64-bit constants.  This is less fragile
-// than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
-// works on compilers that don't have it (like MSVC).
-#if V8_HOST_ARCH_64_BIT
-# if V8_CC_MSVC
-#  define V8_UINT64_C(x)  (x ## UI64)
-#  define V8_INT64_C(x)   (x ## I64)
-#  define V8_INTPTR_C(x)  (x ## I64)
-#  define V8_PTR_PREFIX "ll"
-# elif V8_CC_MINGW
-#  define V8_UINT64_C(x)  (x ## ULL)
-#  define V8_INT64_C(x)   (x ## LL)
-#  define V8_INTPTR_C(x)  (x ## LL)
-#  define V8_PTR_PREFIX "I64"
-# else
-#  define V8_UINT64_C(x)  (x ## UL)
-#  define V8_INT64_C(x)   (x ## L)
-#  define V8_INTPTR_C(x)  (x ## L)
-#  define V8_PTR_PREFIX "l"
-# endif
-#else  // V8_HOST_ARCH_64_BIT
-# define V8_INTPTR_C(x)  (x)
-# define V8_PTR_PREFIX ""
-#endif  // V8_HOST_ARCH_64_BIT
-
-// The following macro works on both 32 and 64-bit platforms.
-// Usage: instead of writing 0x1234567890123456
-//      write V8_2PART_UINT64_C(0x12345678,90123456);
-#define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
-
-#if V8_OS_DARWIN
-// Fix for Mac OS X defining uintptr_t as "unsigned long":
-# define V8PRIxPTR "lx"
-#else
-# define V8PRIxPTR V8_PTR_PREFIX "x"
-#endif  // V8_OS_DARWIN
-#define V8PRIdPTR V8_PTR_PREFIX "d"
-#define V8PRIuPTR V8_PTR_PREFIX "u"
-
-
-// ----------------------------------------------------------------------------
-// Define V8_INFINITY
-#if V8_GNUC_PREREQ(2, 96) && !V8_GNUC_PREREQ(4, 1)
-// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
-// warning flag and certain versions of GCC due to a bug:
-// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
-// For now, we use the more involved template-based version from <limits>, but
-// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
-# include <limits>
-# define V8_INFINITY std::numeric_limits<double>::infinity()
-#elif V8_CC_MSVC
-# define V8_INFINITY HUGE_VAL
+// Determine architecture endiannes (we only support little-endian).
+#if V8_TARGET_ARCH_IA32
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_X64
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_ARM
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_MIPS
+#define V8_TARGET_LITTLE_ENDIAN 1
 #else
-# define V8_INFINITY INFINITY
+#error Unknown target architecture endiannes
 #endif
 
-
-#include "../include/v8stdint.h"
-
-namespace v8 {
-namespace internal {
-
 // Support for alternative bool type. This is only enabled if the code is
 // compiled with USE_MYBOOL defined. This catches some nasty type bugs.
 // For instance, 'bool b = "false";' results in b == true! This is a hidden
@@ -340,6 +183,51 @@ typedef unsigned int __my_bool__;
 typedef uint8_t byte;
 typedef byte* Address;
 
+// Define our own macros for writing 64-bit constants.  This is less fragile
+// than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
+// works on compilers that don't have it (like MSVC).
+#if V8_HOST_ARCH_64_BIT
+#if defined(_MSC_VER)
+#define V8_UINT64_C(x)  (x ## UI64)
+#define V8_INT64_C(x)   (x ## I64)
+#define V8_INTPTR_C(x)  (x ## I64)
+#define V8_PTR_PREFIX "ll"
+#elif defined(__MINGW64__)
+#define V8_UINT64_C(x)  (x ## ULL)
+#define V8_INT64_C(x)   (x ## LL)
+#define V8_INTPTR_C(x)  (x ## LL)
+#define V8_PTR_PREFIX "I64"
+#else
+#define V8_UINT64_C(x)  (x ## UL)
+#define V8_INT64_C(x)   (x ## L)
+#define V8_INTPTR_C(x)  (x ## L)
+#define V8_PTR_PREFIX "l"
+#endif
+#else  // V8_HOST_ARCH_64_BIT
+#define V8_INTPTR_C(x)  (x)
+#define V8_PTR_PREFIX ""
+#endif  // V8_HOST_ARCH_64_BIT
+
+// The following macro works on both 32 and 64-bit platforms.
+// Usage: instead of writing 0x1234567890123456
+//      write V8_2PART_UINT64_C(0x12345678,90123456);
+#define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
+
+#define V8PRIxPTR V8_PTR_PREFIX "x"
+#define V8PRIdPTR V8_PTR_PREFIX "d"
+#define V8PRIuPTR V8_PTR_PREFIX "u"
+
+// Fix for Mac OS X defining uintptr_t as "unsigned long":
+#if defined(__APPLE__) && defined(__MACH__)
+#undef V8PRIxPTR
+#define V8PRIxPTR "lx"
+#endif
+
+#if (defined(__APPLE__) && defined(__MACH__)) || \
+    defined(__FreeBSD__) || defined(__OpenBSD__)
+#define USING_BSD_ABI
+#endif
+
 // -----------------------------------------------------------------------------
 // Constants
 
@@ -442,10 +330,10 @@ F FUNCTION_CAST(Address addr) {
 }
 
 
-#if V8_CXX_DELETED_FUNCTIONS
-# define DISALLOW_BY_DELETE = delete
+#if __cplusplus >= 201103L
+#define DISALLOW_BY_DELETE = delete
 #else
-# define DISALLOW_BY_DELETE
+#define DISALLOW_BY_DELETE
 #endif
 
 
@@ -470,22 +358,24 @@ F FUNCTION_CAST(Address addr) {
 // Define used for helping GCC to make better inlining. Don't bother for debug
 // builds. On GCC 3.4.5 using __attribute__((always_inline)) causes compilation
 // errors in debug build.
-#if V8_GNUC_PREREQ(4, 0) && !defined(DEBUG)
-# define INLINE(header) inline header  __attribute__((always_inline))
-# define NO_INLINE(header) header __attribute__((noinline))
-#elif V8_CC_GNU && !defined(DEBUG)
-# define INLINE(header) inline __attribute__((always_inline)) header
-# define NO_INLINE(header) __attribute__((noinline)) header
-#elif V8_CC_MSVC && !defined(DEBUG)
-# define INLINE(header) __forceinline header
-# define NO_INLINE(header) header
+#if defined(__GNUC__) && !defined(DEBUG)
+#if (__GNUC__ >= 4)
+#define INLINE(header) inline header  __attribute__((always_inline))
+#define NO_INLINE(header) header __attribute__((noinline))
+#else
+#define INLINE(header) inline __attribute__((always_inline)) header
+#define NO_INLINE(header) __attribute__((noinline)) header
+#endif
+#elif defined(_MSC_VER) && !defined(DEBUG)
+#define INLINE(header) __forceinline header
+#define NO_INLINE(header) header
 #else
-# define INLINE(header) inline header
-# define NO_INLINE(header) header
+#define INLINE(header) inline header
+#define NO_INLINE(header) header
 #endif
 
 
-#if V8_GNUC_PREREQ(4, 0)
+#if defined(__GNUC__) && __GNUC__ >= 4
 #define MUST_USE_RESULT __attribute__ ((warn_unused_result))
 #else
 #define MUST_USE_RESULT
diff --git a/deps/v8/src/harmony-array.js b/deps/v8/src/harmony-array.js
new file mode 100644 (file)
index 0000000..e440299
--- /dev/null
@@ -0,0 +1,124 @@
+// 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/deps/v8/src/harmony-string.js b/deps/v8/src/harmony-string.js
new file mode 100644 (file)
index 0000000..a5c6f4e
--- /dev/null
@@ -0,0 +1,154 @@
+// 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 $String = global.String;
+// var $Array = global.Array;
+
+// -------------------------------------------------------------------
+
+// ES6 draft 07-15-13, section 15.5.3.21
+function StringRepeat(count) {
+  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
+    throw MakeTypeError("called_on_null_or_undefined",
+                        ["String.prototype.repeat"]);
+  }
+
+  var s = TO_STRING_INLINE(this);
+  var n = ToInteger(count);
+  if (n < 0 || !NUMBER_IS_FINITE(n)) {
+    throw MakeRangeError("invalid_count_value", []);
+  }
+
+  var elements = new InternalArray(n);
+  for (var i = 0; i < n; i++) {
+    elements[i] = s;
+  }
+
+  return %StringBuilderConcat(elements, n, "");
+}
+
+
+// ES6 draft 07-15-13, section 15.5.3.22
+function StringStartsWith(searchString /* position */) {  // length == 1
+  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
+    throw MakeTypeError("called_on_null_or_undefined",
+                        ["String.prototype.startsWith"]);
+  }
+
+  var s = TO_STRING_INLINE(this);
+  var ss = TO_STRING_INLINE(searchString);
+  var pos = 0;
+  if (%_ArgumentsLength() > 1) {
+    pos = %_Arguments(1);  // position
+    pos = ToInteger(pos);
+  }
+
+  var s_len = s.length;
+  var start = MathMin(MathMax(pos, 0), s_len);
+  var ss_len = ss.length;
+  if (ss_len + start > s_len) {
+    return false;
+  }
+
+  return %StringIndexOf(s, ss, start) === start;
+}
+
+
+// ES6 draft 07-15-13, section 15.5.3.23
+function StringEndsWith(searchString /* position */) {  // length == 1
+  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
+    throw MakeTypeError("called_on_null_or_undefined",
+                        ["String.prototype.endsWith"]);
+  }
+
+  var s = TO_STRING_INLINE(this);
+  var ss = TO_STRING_INLINE(searchString);
+  var s_len = s.length;
+  var pos = s_len;
+  if (%_ArgumentsLength() > 1) {
+    var arg = %_Arguments(1);  // position
+    if (!IS_UNDEFINED(arg)) {
+      pos = ToInteger(arg);
+    }
+  }
+
+  var end = MathMin(MathMax(pos, 0), s_len);
+  var ss_len = ss.length;
+  var start = end - ss_len;
+  if (start < 0) {
+    return false;
+  }
+
+  return %StringLastIndexOf(s, ss, start) === start;
+}
+
+
+// ES6 draft 07-15-13, section 15.5.3.24
+function StringContains(searchString /* position */) {  // length == 1
+  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
+    throw MakeTypeError("called_on_null_or_undefined",
+                        ["String.prototype.contains"]);
+  }
+
+  var s = TO_STRING_INLINE(this);
+  var ss = TO_STRING_INLINE(searchString);
+  var pos = 0;
+  if (%_ArgumentsLength() > 1) {
+    pos = %_Arguments(1);  // position
+    pos = ToInteger(pos);
+  }
+
+  var s_len = s.length;
+  var start = MathMin(MathMax(pos, 0), s_len);
+  var ss_len = ss.length;
+  if (ss_len + start > s_len) {
+    return false;
+  }
+
+  return %StringIndexOf(s, ss, start) !== -1;
+}
+
+
+// -------------------------------------------------------------------
+
+function ExtendStringPrototype() {
+  %CheckIsBootstrapping();
+
+  // Set up the non-enumerable functions on the String prototype object.
+  InstallFunctions($String.prototype, DONT_ENUM, $Array(
+    "repeat", StringRepeat,
+    "startsWith", StringStartsWith,
+    "endsWith", StringEndsWith,
+    "contains", StringContains
+  ));
+}
+
+ExtendStringPrototype();
\ No newline at end of file
index 9f9f84a..1c8a7b3 100644 (file)
@@ -369,6 +369,12 @@ 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),
@@ -393,19 +399,20 @@ void HeapObjectsMap::MoveObject(Address from, Address to) {
   ASSERT(to != NULL);
   ASSERT(from != NULL);
   if (from == to) return;
-  void* from_value = entries_map_.Remove(from, AddressHash(from));
+  void* from_value = entries_map_.Remove(from, ComputePointerHash(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, AddressHash(to));
+    void* to_value = entries_map_.Remove(to, ComputePointerHash(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, AddressHash(to), true);
+    HashMap::Entry* to_entry = entries_map_.Lookup(to, ComputePointerHash(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
@@ -425,7 +432,8 @@ void HeapObjectsMap::MoveObject(Address from, Address to) {
 
 
 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
-  HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false);
+  HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(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);
@@ -437,7 +445,8 @@ 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, AddressHash(addr), true);
+  HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr),
+                                              true);
   if (entry->value != NULL) {
     int entry_index =
         static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
@@ -532,13 +541,14 @@ void HeapObjectsMap::RemoveDeadEntries() {
       }
       entries_.at(first_free_entry).accessed = false;
       HashMap::Entry* entry = entries_map_.Lookup(
-          entry_info.addr, AddressHash(entry_info.addr), false);
+          entry_info.addr, ComputePointerHash(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, AddressHash(entry_info.addr));
+        entries_map_.Remove(entry_info.addr,
+                            ComputePointerHash(entry_info.addr));
       }
     }
   }
index 31d8088..cea9958 100644 (file)
@@ -266,16 +266,6 @@ 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_;
index 692ec21..53088e2 100644 (file)
@@ -1014,6 +1014,8 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
   }
   gc_post_processing_depth_--;
 
+  isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
+
   // Update relocatables.
   Relocatable::PostGarbageCollectionProcessing();
 
@@ -2006,7 +2008,6 @@ 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;
@@ -2058,15 +2059,12 @@ class ScavengingVisitor : public StaticVisitorBase {
   }
 
 
-  template<ObjectContents object_contents,
-           SizeRestriction size_restriction,
-           int alignment>
+  template<ObjectContents object_contents, int alignment>
   static inline void EvacuateObject(Map* map,
                                     HeapObject** slot,
                                     HeapObject* object,
                                     int object_size) {
-    SLOW_ASSERT((size_restriction != SMALL) ||
-                (object_size <= Page::kMaxNonCodeHeapObjectSize));
+    SLOW_ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
     SLOW_ASSERT(object->Size() == object_size);
 
     int allocation_size = object_size;
@@ -2079,17 +2077,11 @@ class ScavengingVisitor : public StaticVisitorBase {
     if (heap->ShouldBePromoted(object->address(), object_size)) {
       MaybeObject* maybe_result;
 
-      if ((size_restriction != SMALL) &&
-          (allocation_size > Page::kMaxNonCodeHeapObjectSize)) {
-        maybe_result = heap->lo_space()->AllocateRaw(allocation_size,
-                                                     NOT_EXECUTABLE);
+      if (object_contents == DATA_OBJECT) {
+        maybe_result = heap->old_data_space()->AllocateRaw(allocation_size);
       } else {
-        if (object_contents == DATA_OBJECT) {
-          maybe_result = heap->old_data_space()->AllocateRaw(allocation_size);
-        } else {
-          maybe_result =
-              heap->old_pointer_space()->AllocateRaw(allocation_size);
-        }
+        maybe_result =
+            heap->old_pointer_space()->AllocateRaw(allocation_size);
       }
 
       Object* result = NULL;  // Initialization to please compiler.
@@ -2163,10 +2155,8 @@ class ScavengingVisitor : public StaticVisitorBase {
                                         HeapObject** slot,
                                         HeapObject* object) {
     int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
-    EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(map,
-                                                 slot,
-                                                 object,
-                                                 object_size);
+    EvacuateObject<POINTER_OBJECT, kObjectAlignment>(
+        map, slot, object, object_size);
   }
 
 
@@ -2175,11 +2165,8 @@ class ScavengingVisitor : public StaticVisitorBase {
                                               HeapObject* object) {
     int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
     int object_size = FixedDoubleArray::SizeFor(length);
-    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kDoubleAlignment>(
-        map,
-        slot,
-        object,
-        object_size);
+    EvacuateObject<DATA_OBJECT, kDoubleAlignment>(
+        map, slot, object, object_size);
   }
 
 
@@ -2187,7 +2174,7 @@ class ScavengingVisitor : public StaticVisitorBase {
                                        HeapObject** slot,
                                        HeapObject* object) {
     int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
-    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(
+    EvacuateObject<DATA_OBJECT, kObjectAlignment>(
         map, slot, object, object_size);
   }
 
@@ -2197,7 +2184,7 @@ class ScavengingVisitor : public StaticVisitorBase {
                                             HeapObject* object) {
     int object_size = SeqOneByteString::cast(object)->
         SeqOneByteStringSize(map->instance_type());
-    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(
+    EvacuateObject<DATA_OBJECT, kObjectAlignment>(
         map, slot, object, object_size);
   }
 
@@ -2207,7 +2194,7 @@ class ScavengingVisitor : public StaticVisitorBase {
                                               HeapObject* object) {
     int object_size = SeqTwoByteString::cast(object)->
         SeqTwoByteStringSize(map->instance_type());
-    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE, kObjectAlignment>(
+    EvacuateObject<DATA_OBJECT, kObjectAlignment>(
         map, slot, object, object_size);
   }
 
@@ -2251,7 +2238,7 @@ class ScavengingVisitor : public StaticVisitorBase {
     }
 
     int object_size = ConsString::kSize;
-    EvacuateObject<POINTER_OBJECT, SMALL, kObjectAlignment>(
+    EvacuateObject<POINTER_OBJECT, kObjectAlignment>(
         map, slot, object, object_size);
   }
 
@@ -2262,7 +2249,7 @@ class ScavengingVisitor : public StaticVisitorBase {
     static inline void VisitSpecialized(Map* map,
                                         HeapObject** slot,
                                         HeapObject* object) {
-      EvacuateObject<object_contents, SMALL, kObjectAlignment>(
+      EvacuateObject<object_contents, kObjectAlignment>(
           map, slot, object, object_size);
     }
 
@@ -2270,7 +2257,7 @@ class ScavengingVisitor : public StaticVisitorBase {
                              HeapObject** slot,
                              HeapObject* object) {
       int object_size = map->instance_size();
-      EvacuateObject<object_contents, SMALL, kObjectAlignment>(
+      EvacuateObject<object_contents, kObjectAlignment>(
           map, slot, object, object_size);
     }
   };
@@ -3202,6 +3189,11 @@ bool Heap::CreateInitialObjects() {
   }
   set_frozen_symbol(Symbol::cast(obj));
 
+  { MaybeObject* maybe_obj = AllocateSymbol();
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_elements_transition_symbol(Symbol::cast(obj));
+
   { MaybeObject* maybe_obj = SeededNumberDictionary::Allocate(this, 0, TENURED);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
@@ -3213,9 +3205,6 @@ 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));
 
@@ -6603,6 +6592,14 @@ 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);
@@ -6945,6 +6942,8 @@ void Heap::TearDown() {
 
   external_string_table_.TearDown();
 
+  mark_compact_collector()->TearDown();
+
   new_space_.TearDown();
 
   if (old_pointer_space_ != NULL) {
index fbe0531..1b6bf8e 100644 (file)
@@ -178,7 +178,7 @@ namespace internal {
   V(Smi, last_script_id, LastScriptId)                                         \
   V(Script, empty_script, EmptyScript)                                         \
   V(Smi, real_stack_limit, RealStackLimit)                                     \
-  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)        \
+  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)          \
   V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset)     \
   V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset)           \
   V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)                 \
@@ -186,11 +186,10 @@ namespace internal {
   V(JSObject, observation_state, ObservationState)                             \
   V(Map, external_map, ExternalMap)                                            \
   V(Symbol, frozen_symbol, FrozenSymbol)                                       \
+  V(Symbol, elements_transition_symbol, ElementsTransitionSymbol)              \
   V(SeededNumberDictionary, empty_slow_element_dictionary,                     \
       EmptySlowElementDictionary)                                              \
-  V(Symbol, observed_symbol, ObservedSymbol)                                   \
-  V(HeapObject, i18n_template_one, I18nTemplateOne)                            \
-  V(HeapObject, i18n_template_two, I18nTemplateTwo)
+  V(Symbol, observed_symbol, ObservedSymbol)
 
 #define ROOT_LIST(V)                                  \
   STRONG_ROOT_LIST(V)                                 \
@@ -482,6 +481,7 @@ enum ArrayStorageAllocationMode {
   INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
 };
 
+
 class Heap {
  public:
   // Configure heap size before setup. Return false if the heap has been
@@ -1300,12 +1300,6 @@ 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.
@@ -1398,7 +1392,7 @@ class Heap {
 
   // Finds out which space an object should get promoted to based on its type.
   inline OldSpace* TargetSpace(HeapObject* object);
-  inline AllocationSpace TargetSpaceId(InstanceType type);
+  static inline AllocationSpace TargetSpaceId(InstanceType type);
 
   // Sets the stub_cache_ (only used when expanding the dictionary).
   void public_set_code_stubs(UnseededNumberDictionary* value) {
@@ -1545,19 +1539,16 @@ class Heap {
   MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int length,
                                                      PretenureFlag pretenure);
 
-  // Predicate that governs global pre-tenuring decisions based on observed
-  // promotion rates of previous collections.
-  inline bool ShouldGloballyPretenure() {
-    return FLAG_pretenuring && new_space_high_promotion_mode_active_;
-  }
-
   // This is only needed for testing high promotion mode.
   void SetNewSpaceHighPromotionModeActive(bool mode) {
     new_space_high_promotion_mode_active_ = mode;
   }
 
+  // Returns the allocation mode (pre-tenuring) based on observed promotion
+  // rates of previous collections.
   inline PretenureFlag GetPretenureMode() {
-    return new_space_high_promotion_mode_active_ ? TENURED : NOT_TENURED;
+    return FLAG_pretenuring && new_space_high_promotion_mode_active_
+        ? TENURED : NOT_TENURED;
   }
 
   inline Address* NewSpaceHighPromotionModeActiveAddress() {
index ff0b072..7c81ec1 100644 (file)
@@ -260,12 +260,12 @@ class BoundsCheckBbData: public ZoneObject {
     HValue* index_context = IndexContext(*add, check);
     if (index_context == NULL) return false;
 
-    HConstant* new_constant = new(BasicBlock()->zone()) HConstant(
-        new_offset, representation);
+    Zone* zone = BasicBlock()->zone();
+    HConstant* new_constant = HConstant::New(zone, index_context,
+                                             new_offset, representation);
     if (*add == NULL) {
       new_constant->InsertBefore(check);
-      (*add) = HAdd::New(
-          BasicBlock()->zone(), index_context, original_value, new_constant);
+      (*add) = HAdd::New(zone, index_context, original_value, new_constant);
       (*add)->AssumeRepresentation(representation);
       (*add)->InsertBefore(check);
     } else {
index 8646747..137d629 100644 (file)
@@ -278,10 +278,12 @@ class InductionVariableBlocksTable BASE_EMBEDDED {
     }
 
     // Choose the appropriate limit.
+    Zone* zone = graph()->zone();
+    HValue* context = graph()->GetInvalidContext();
     HValue* limit = data->limit();
     if (has_upper_constant_limit) {
-      HConstant* new_limit = new(pre_header->graph()->zone()) HConstant(
-          upper_constant_limit, length->representation());
+      HConstant* new_limit = HConstant::New(zone, context,
+                                            upper_constant_limit);
       new_limit->InsertBefore(pre_header->end());
       limit = new_limit;
     }
@@ -290,15 +292,15 @@ class InductionVariableBlocksTable BASE_EMBEDDED {
     if (limit->IsInteger32Constant() &&
         limit->block() != pre_header &&
         !limit->block()->Dominates(pre_header)) {
-      HConstant* new_limit = new(pre_header->graph()->zone()) HConstant(
-          limit->GetInteger32Constant(), length->representation());
+      HConstant* new_limit = HConstant::New(zone, context,
+                                            limit->GetInteger32Constant());
       new_limit->InsertBefore(pre_header->end());
       limit = new_limit;
     }
 
     // Do the hoisting.
-    HBoundsCheck* hoisted_check = new(pre_header->zone()) HBoundsCheck(
-        limit, check->check()->length());
+    HBoundsCheck* hoisted_check = HBoundsCheck::New(
+        zone, context, limit, check->check()->length());
     hoisted_check->InsertBefore(pre_header->end());
     hoisted_check->set_allow_equality(true);
     hoisted_check->block()->graph()->isolate()->counters()->
index 696d22c..67e6718 100644 (file)
@@ -38,7 +38,7 @@ static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
   HConstant* constant;
   HValue* subexpression;
   HBinaryOperation* binary_operation = HBinaryOperation::cast(index);
-  if (binary_operation->left()->IsConstant()) {
+  if (binary_operation->left()->IsConstant() && index->IsAdd()) {
     subexpression = binary_operation->right();
     constant = HConstant::cast(binary_operation->left());
   } else if (binary_operation->right()->IsConstant()) {
index 54b53db..997b7c2 100644 (file)
@@ -149,116 +149,6 @@ 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) {
@@ -484,55 +374,6 @@ 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();
 }
@@ -960,58 +801,6 @@ 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);
 }
@@ -1038,40 +827,6 @@ 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;
 
@@ -1091,12 +846,13 @@ void HBoundsCheck::ApplyIndexChange() {
   int actual_offset = decomposition.offset() + offset();
   int actual_scale = decomposition.scale() + scale();
 
+  Zone* zone = block()->graph()->zone();
+  HValue* context = block()->graph()->GetInvalidContext();
   if (actual_offset != 0) {
-    HConstant* add_offset = new(block()->graph()->zone()) HConstant(
-        actual_offset, index()->representation());
+    HConstant* add_offset = HConstant::New(zone, context, actual_offset);
     add_offset->InsertBefore(this);
-    HInstruction* add = HAdd::New(block()->graph()->zone(),
-        block()->graph()->GetInvalidContext(), current_index, add_offset);
+    HInstruction* add = HAdd::New(zone, context,
+                                  current_index, add_offset);
     add->InsertBefore(this);
     add->AssumeRepresentation(index()->representation());
     add->ClearFlag(kCanOverflow);
@@ -1104,11 +860,10 @@ void HBoundsCheck::ApplyIndexChange() {
   }
 
   if (actual_scale != 0) {
-    HConstant* sar_scale = new(block()->graph()->zone()) HConstant(
-        actual_scale, index()->representation());
+    HConstant* sar_scale = HConstant::New(zone, context, actual_scale);
     sar_scale->InsertBefore(this);
-    HInstruction* sar = HSar::New(block()->graph()->zone(),
-        block()->graph()->GetInvalidContext(), current_index, sar_scale);
+    HInstruction* sar = HSar::New(zone, context,
+                                  current_index, sar_scale);
     sar->InsertBefore(this);
     sar->AssumeRepresentation(index()->representation());
     current_index = sar;
@@ -1119,40 +874,6 @@ 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;
-  }
 }
 
 
@@ -1195,25 +916,6 @@ 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);
@@ -1453,6 +1155,29 @@ 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.
@@ -1465,18 +1190,10 @@ HValue* HBitwise::Canonicalize() {
       !left()->CheckFlag(kUint32)) {
     return left();
   }
-  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;
-    }
+  // Optimize double negation, a common pattern used for ToInt32(x).
+  HValue* arg;
+  if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) {
+    return arg;
   }
   return this;
 }
@@ -1612,8 +1329,8 @@ HValue* HUnaryMathOperation::Canonicalize() {
           !HInstruction::cast(new_right)->IsLinked()) {
         HInstruction::cast(new_right)->InsertBefore(this);
       }
-      HMathFloorOfDiv* instr = new(block()->zone())
-          HMathFloorOfDiv(context(), new_left, new_right);
+      HMathFloorOfDiv* instr =
+          HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right);
       // Replace this HMathFloor instruction by the new HMathFloorOfDiv.
       instr->InsertBefore(this);
       ReplaceAllUsesWith(instr);
@@ -1633,11 +1350,13 @@ HValue* HUnaryMathOperation::Canonicalize() {
 
 HValue* HCheckInstanceType::Canonicalize() {
   if (check_ == IS_STRING && value()->type().IsString()) {
-    return NULL;
+    return value();
   }
 
   if (check_ == IS_INTERNALIZED_STRING && value()->IsConstant()) {
-    if (HConstant::cast(value())->HasInternalizedStringValue()) return NULL;
+    if (HConstant::cast(value())->HasInternalizedStringValue()) {
+      return value();
+    }
   }
   return this;
 }
@@ -1685,10 +1404,10 @@ void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
   // for which the map is known.
   if (HasNoUses() && dominator->IsStoreNamedField()) {
     HStoreNamedField* store = HStoreNamedField::cast(dominator);
-    UniqueValueId map_unique_id = store->transition_unique_id();
-    if (!map_unique_id.IsInitialized() || store->object() != value()) return;
+    if (!store->has_transition() || store->object() != value()) return;
+    HConstant* transition = HConstant::cast(store->transition());
     for (int i = 0; i < map_set()->length(); i++) {
-      if (map_unique_id == map_unique_ids_.at(i)) {
+      if (transition->UniqueValueIdsMatch(map_unique_ids_.at(i))) {
         DeleteAndReplaceWith(NULL);
         return;
       }
@@ -1739,13 +1458,6 @@ 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));
@@ -1948,60 +1660,6 @@ 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;
@@ -2129,8 +1787,8 @@ void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock(
   HValue* previous_index = first_check_in_block()->index();
   ASSERT(context != NULL);
 
-  set_added_constant(new(index_base->block()->graph()->zone()) HConstant(
-      mask, index_base->representation()));
+  Zone* zone = index_base->block()->graph()->zone();
+  set_added_constant(HConstant::New(zone, context, mask));
   if (added_index() != NULL) {
     added_constant()->InsertBefore(added_index());
   } else {
@@ -2139,9 +1797,8 @@ void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock(
 
   if (added_index() == NULL) {
     first_check_in_block()->ReplaceAllUsesWith(first_check_in_block()->index());
-    HInstruction* new_index =  HBitwise::New(
-        index_base->block()->graph()->zone(),
-        token, context, index_base, added_constant());
+    HInstruction* new_index =  HBitwise::New(zone, context, token, index_base,
+                                             added_constant());
     ASSERT(new_index->IsBitwise());
     new_index->ClearAllSideEffects();
     new_index->AssumeRepresentation(Representation::Integer32());
@@ -2640,7 +2297,8 @@ static bool IsInteger32(double value) {
 
 
 HConstant::HConstant(Handle<Object> handle, Representation r)
-  : handle_(handle),
+  : HTemplateInstruction<0>(HType::TypeFromValue(handle)),
+    handle_(handle),
     unique_id_(),
     has_smi_value_(false),
     has_int32_value_(false),
@@ -2650,8 +2308,6 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
     is_not_in_new_space_(true),
     is_cell_(false),
     boolean_value_(handle->BooleanValue()) {
-  set_type(HType::TypeFromValue(handle));
-
   if (handle_->IsHeapObject()) {
     Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap();
     is_not_in_new_space_ = !heap->InNewSpace(*handle);
@@ -2681,7 +2337,8 @@ HConstant::HConstant(Handle<Object> handle,
                      bool is_not_in_new_space,
                      bool is_cell,
                      bool boolean_value)
-  : handle_(handle),
+  : HTemplateInstruction<0>(type),
+    handle_(handle),
     unique_id_(unique_id),
     has_smi_value_(false),
     has_int32_value_(false),
@@ -2693,7 +2350,6 @@ HConstant::HConstant(Handle<Object> handle,
     boolean_value_(boolean_value) {
   ASSERT(!handle.is_null());
   ASSERT(!type.IsTaggedNumber());
-  set_type(type);
   Initialize(r);
 }
 
@@ -2741,7 +2397,8 @@ HConstant::HConstant(double double_value,
 
 
 HConstant::HConstant(ExternalReference reference)
-  : has_smi_value_(false),
+  : HTemplateInstruction<0>(HType::None()),
+    has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
     has_external_reference_value_(true),
@@ -2750,11 +2407,18 @@ HConstant::HConstant(ExternalReference reference)
     is_cell_(false),
     boolean_value_(true),
     external_reference_value_(reference) {
-  set_type(HType::None());
   Initialize(Representation::External());
 }
 
 
+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) {
@@ -2766,6 +2430,7 @@ void HConstant::Initialize(Representation r) {
     } else if (has_external_reference_value_) {
       r = Representation::External();
     } else {
+      PrepareConstant(handle_);
       r = Representation::Tagged();
     }
   }
@@ -3050,6 +2715,14 @@ Range* HShl::InferRange(Zone* zone) {
 }
 
 
+Range* HLoadNamedField::InferRange(Zone* zone) {
+  if (access().IsStringLength()) {
+    return new(zone) Range(0, String::kMaxLength);
+  }
+  return HValue::InferRange(zone);
+}
+
+
 Range* HLoadKeyed::InferRange(Zone* zone) {
   switch (elements_kind()) {
     case EXTERNAL_PIXEL_ELEMENTS:
@@ -3082,16 +2755,6 @@ 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(" ");
@@ -3282,13 +2945,15 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
 }
 
 
-HCheckMaps* HCheckMaps::New(HValue* value,
+HCheckMaps* HCheckMaps::New(Zone* zone,
+                            HValue* context,
+                            HValue* value,
                             Handle<Map> map,
-                            Zone* zone,
                             CompilationInfo* info,
                             HValue* typecheck) {
   HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
   check_map->map_set_.Add(map, zone);
+  check_map->has_migration_target_ = map->is_migration_target();
   if (map->CanOmitMapChecks() &&
       value->IsConstant() &&
       HConstant::cast(value)->InstanceOf(map)) {
@@ -3298,39 +2963,6 @@ HCheckMaps* HCheckMaps::New(HValue* value,
 }
 
 
-HCheckMaps* HCheckMaps::NewWithTransitions(HValue* value,
-                                           Handle<Map> map,
-                                           Zone* zone,
-                                           CompilationInfo* info) {
-  HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, value);
-  check_map->map_set_.Add(map, zone);
-
-  // Since transitioned elements maps of the initial map don't fail the map
-  // check, the CheckMaps instruction doesn't need to depend on ElementsKinds.
-  check_map->ClearGVNFlag(kDependsOnElementsKind);
-
-  ElementsKind kind = map->elements_kind();
-  bool packed = IsFastPackedElementsKind(kind);
-  while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
-    kind = GetNextMoreGeneralFastElementsKind(kind, packed);
-    Map* transitioned_map =
-        map->LookupElementsTransitionMap(kind);
-    if (transitioned_map) {
-      check_map->map_set_.Add(Handle<Map>(transitioned_map), zone);
-    }
-  };
-
-  if (map->CanOmitMapChecks() &&
-      value->IsConstant() &&
-      HConstant::cast(value)->InstanceOf(map)) {
-    check_map->omit(info);
-  }
-
-  check_map->map_set_.Sort();
-  return check_map;
-}
-
-
 void HCheckMaps::FinalizeUniqueValueId() {
   if (!map_unique_ids_.is_empty()) return;
   Zone* zone = block()->zone();
@@ -3503,8 +3135,13 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
         HForInCacheArray* index_cache =
             names_cache->index_cache();
         HCheckMapValue* map_check =
-            new(block()->zone()) HCheckMapValue(object(), names_cache->map());
-        HInstruction* index = new(block()->zone()) HLoadKeyed(
+            HCheckMapValue::New(block()->graph()->zone(),
+                                block()->graph()->GetInvalidContext(),
+                                object(),
+                                names_cache->map());
+        HInstruction* index = HLoadKeyed::New(
+            block()->graph()->zone(),
+            block()->graph()->GetInvalidContext(),
             index_cache,
             key_load->key(),
             key_load->key(),
@@ -3541,8 +3178,8 @@ void HStoreNamedField::PrintDataTo(StringStream* stream) {
   if (NeedsWriteBarrier()) {
     stream->Add(" (write-barrier)");
   }
-  if (!transition().is_null()) {
-    stream->Add(" (transition map %p)", *transition());
+  if (has_transition()) {
+    stream->Add(" (transition map %p)", *transition_map());
   }
 }
 
@@ -3633,12 +3270,6 @@ void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
 }
 
 
-void HLinkObjectInList::PrintDataTo(StringStream* stream) {
-  value()->PrintNameTo(stream);
-  stream->Add(" offset %d", store_field_.offset());
-}
-
-
 void HLoadContextSlot::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add("[%d]", slot_index());
@@ -3660,26 +3291,6 @@ HType HValue::CalculateInferredType() {
 }
 
 
-HType HCheckMaps::CalculateInferredType() {
-  return value()->type();
-}
-
-
-HType HCheckFunction::CalculateInferredType() {
-  return value()->type();
-}
-
-
-HType HCheckHeapObject::CalculateInferredType() {
-  return HType::NonPrimitive();
-}
-
-
-HType HCheckSmi::CalculateInferredType() {
-  return HType::Smi();
-}
-
-
 HType HPhi::CalculateInferredType() {
   if (OperandCount() == 0) return HType::Tagged();
   HType result = OperandAt(0)->type();
@@ -3691,52 +3302,12 @@ HType HPhi::CalculateInferredType() {
 }
 
 
-HType HCompareGeneric::CalculateInferredType() {
-  return HType::Boolean();
-}
-
-
-HType HInstanceOf::CalculateInferredType() {
-  return HType::Boolean();
-}
-
-
-HType HInstanceOfKnownGlobal::CalculateInferredType() {
-  return HType::Boolean();
-}
-
-
 HType HChange::CalculateInferredType() {
   if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
   return type();
 }
 
 
-HType HBitwiseBinaryOperation::CalculateInferredType() {
-  return HType::TaggedNumber();
-}
-
-
-HType HArithmeticBinaryOperation::CalculateInferredType() {
-  return HType::TaggedNumber();
-}
-
-
-HType HAdd::CalculateInferredType() {
-  return HType::Tagged();
-}
-
-
-HType HBitNot::CalculateInferredType() {
-  return HType::TaggedNumber();
-}
-
-
-HType HUnaryMathOperation::CalculateInferredType() {
-  return HType::TaggedNumber();
-}
-
-
 Representation HUnaryMathOperation::RepresentationFromInputs() {
   Representation rep = representation();
   // If any of the actual input representation is more general than what we
@@ -3766,8 +3337,8 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
   HValue* current_size = size();
   // We can just fold allocations that are guaranteed in new space.
   // TODO(hpayer): Add support for non-constant allocation in dominator.
-  if (!GuaranteedInNewSpace() || !current_size->IsInteger32Constant() ||
-      !dominator_allocate_instr->GuaranteedInNewSpace() ||
+  if (!IsNewSpaceAllocation() || !current_size->IsInteger32Constant() ||
+      !dominator_allocate_instr->IsNewSpaceAllocation() ||
       !dominator_size->IsInteger32Constant()) {
     if (FLAG_trace_allocation_folding) {
       PrintF("#%d (%s) cannot fold into #%d (%s)\n",
@@ -3785,7 +3356,7 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
 
   if (MustAllocateDoubleAligned()) {
     if (!dominator_allocate_instr->MustAllocateDoubleAligned()) {
-      dominator_allocate_instr->SetFlags(HAllocate::ALLOCATE_DOUBLE_ALIGNED);
+      dominator_allocate_instr->MakeDoubleAligned();
     }
     if ((dominator_size_constant & kDoubleAlignmentMask) != 0) {
       dominator_size_constant += kDoubleSize / 2;
@@ -3803,22 +3374,24 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
   }
   HBasicBlock* block = dominator->block();
   Zone* zone = block->zone();
-  HInstruction* new_dominator_size_constant = new(zone) HConstant(
-      new_dominator_size);
+  HInstruction* new_dominator_size_constant =
+      HConstant::New(zone, context(), new_dominator_size);
   new_dominator_size_constant->InsertBefore(dominator_allocate_instr);
   dominator_allocate_instr->UpdateSize(new_dominator_size_constant);
 
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) {
-    dominator_allocate_instr->SetFlags(HAllocate::PREFILL_WITH_FILLER);
+    dominator_allocate_instr->MakePrefillWithFiller();
   }
 #endif
 
   // After that replace the dominated allocate instruction.
   HInstruction* dominated_allocate_instr =
-      new(zone) HInnerAllocatedObject(dominator_allocate_instr,
-                                      dominator_size_constant,
-                                      type());
+      HInnerAllocatedObject::New(zone,
+                                 context(),
+                                 dominator_allocate_instr,
+                                 dominator_size_constant,
+                                 type());
   dominated_allocate_instr->InsertBefore(this);
   DeleteAndReplaceWith(dominated_allocate_instr);
   if (FLAG_trace_allocation_folding) {
@@ -3830,17 +3403,13 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
 
 void HAllocate::PrintDataTo(StringStream* stream) {
   size()->PrintNameTo(stream);
-  if (!GuaranteedInNewSpace()) stream->Add(" (pretenure)");
-}
-
-
-HType HRegExpLiteral::CalculateInferredType() {
-  return HType::JSObject();
-}
-
-
-HType HFunctionLiteral::CalculateInferredType() {
-  return HType::JSObject();
+  stream->Add(" (");
+  if (IsNewSpaceAllocation()) stream->Add("N");
+  if (IsOldPointerSpaceAllocation()) stream->Add("P");
+  if (IsOldDataSpaceAllocation()) stream->Add("D");
+  if (MustAllocateDoubleAligned()) stream->Add("A");
+  if (MustPrefillWithFiller()) stream->Add("F");
+  stream->Add(")");
 }
 
 
@@ -3966,10 +3535,10 @@ bool HStoreKeyed::NeedsCanonicalization() {
 }
 
 
-#define H_CONSTANT_INT(val)                                                  \
-new(zone) HConstant(static_cast<int32_t>(val))
+#define H_CONSTANT_INT(val)                                                    \
+HConstant::New(zone, context, static_cast<int32_t>(val))
 #define H_CONSTANT_DOUBLE(val)                                                 \
-new(zone) HConstant(static_cast<double>(val), Representation::Double())
+HConstant::New(zone, context, static_cast<double>(val))
 
 #define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op)                       \
 HInstruction* HInstr::New(                                                     \
@@ -3980,7 +3549,7 @@ HInstruction* HInstr::New(                                                     \
     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
       double double_res = c_left->DoubleValue() op c_right->DoubleValue();     \
       if (TypeInfo::IsInt32Double(double_res)) {                               \
-        return H_CONSTANT_INT(double_res);                                   \
+        return H_CONSTANT_INT(double_res);                                     \
       }                                                                        \
       return H_CONSTANT_DOUBLE(double_res);                                    \
     }                                                                          \
@@ -4007,7 +3576,7 @@ HInstruction* HStringAdd::New(Zone* zone,
     if (c_left->HasStringValue() && c_right->HasStringValue()) {
       Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString(
           c_left->StringValue(), c_right->StringValue());
-      return new(zone) HConstant(concat, Representation::Tagged());
+      return HConstant::New(zone, context, concat);
     }
   }
   return new(zone) HStringAdd(context, left, right, flags);
@@ -4022,29 +3591,16 @@ HInstruction* HStringCharFromCode::New(
     if (c_code->HasNumberValue()) {
       if (std::isfinite(c_code->DoubleValue())) {
         uint32_t code = c_code->NumberValueAsInteger32() & 0xffff;
-        return new(zone) HConstant(LookupSingleCharacterStringFromCode(isolate,
-                                                                       code),
-                                   Representation::Tagged());
+        return HConstant::New(zone, context,
+            LookupSingleCharacterStringFromCode(isolate, code));
       }
-      return new(zone) HConstant(isolate->factory()->empty_string(),
-                                 Representation::Tagged());
+      return HConstant::New(zone, context, isolate->factory()->empty_string());
     }
   }
   return new(zone) HStringCharFromCode(context, char_code);
 }
 
 
-HInstruction* HStringLength::New(Zone* zone, HValue* string) {
-  if (FLAG_fold_constants && string->IsConstant()) {
-    HConstant* c_string = HConstant::cast(string);
-    if (c_string->HasStringValue()) {
-      return new(zone) HConstant(c_string->StringValue()->length());
-    }
-  }
-  return new(zone) HStringLength(string);
-}
-
-
 HInstruction* HUnaryMathOperation::New(
     Zone* zone, HValue* context, HValue* value, BuiltinFunctionId op) {
   do {
@@ -4113,7 +3669,10 @@ HInstruction* HUnaryMathOperation::New(
 }
 
 
-HInstruction* HPower::New(Zone* zone, HValue* left, HValue* right) {
+HInstruction* HPower::New(Zone* zone,
+                          HValue* context,
+                          HValue* left,
+                          HValue* right) {
   if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
     HConstant* c_left = HConstant::cast(left);
     HConstant* c_right = HConstant::cast(right);
@@ -4212,7 +3771,7 @@ HInstruction* HDiv::New(
 
 
 HInstruction* HBitwise::New(
-    Zone* zone, Token::Value op, HValue* context, HValue* left, HValue* right) {
+    Zone* zone, HValue* context, Token::Value op, HValue* left, HValue* right) {
   if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
     HConstant* c_left = HConstant::cast(left);
     HConstant* c_right = HConstant::cast(right);
@@ -4237,7 +3796,7 @@ HInstruction* HBitwise::New(
       return H_CONSTANT_INT(result);
     }
   }
-  return new(zone) HBitwise(op, context, left, right);
+  return new(zone) HBitwise(context, op, left, right);
 }
 
 
@@ -4306,7 +3865,8 @@ void HPhi::SimplifyConstantInputs() {
       continue;
     } else if (operand->HasDoubleValue()) {
       HConstant* integer_input =
-          new(graph->zone()) HConstant(DoubleToInt32(operand->DoubleValue()));
+          HConstant::New(graph->zone(), graph->GetInvalidContext(),
+                         DoubleToInt32(operand->DoubleValue()));
       integer_input->InsertAfter(operand);
       SetOperandAt(i, integer_input);
     } else if (operand == graph->GetConstantTrue()) {
@@ -4518,6 +4078,10 @@ void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
       instr->SetGVNFlag(is_store
           ? kChangesArrayLengths : kDependsOnArrayLengths);
       break;
+    case kStringLengths:
+      instr->SetGVNFlag(is_store
+          ? kChangesStringLengths : kDependsOnStringLengths);
+      break;
     case kInobject:
       instr->SetGVNFlag(is_store
           ? kChangesInobjectFields : kDependsOnInobjectFields);
@@ -4551,6 +4115,7 @@ void HObjectAccess::PrintTo(StringStream* stream) {
 
   switch (portion()) {
     case kArrayLengths:
+    case kStringLengths:
       stream->Add("%length");
       break;
     case kElementsPointer:
index e71b7cd..3fae45b 100644 (file)
@@ -72,7 +72,6 @@ class LChunkBuilder;
   V(ArgumentsLength)                           \
   V(ArgumentsObject)                           \
   V(Bitwise)                                   \
-  V(BitNot)                                    \
   V(BlockEntry)                                \
   V(BoundsCheck)                               \
   V(BoundsCheckBaseIndexInformation)           \
@@ -93,7 +92,6 @@ class LChunkBuilder;
   V(CheckInstanceType)                         \
   V(CheckMaps)                                 \
   V(CheckMapValue)                             \
-  V(CheckPrototypeMaps)                        \
   V(CheckSmi)                                  \
   V(ClampToUint8)                              \
   V(ClassOfTestAndBranch)                      \
@@ -122,7 +120,6 @@ class LChunkBuilder;
   V(Goto)                                      \
   V(HasCachedArrayIndexAndBranch)              \
   V(HasInstanceTypeAndBranch)                  \
-  V(InductionVariableAnnotation)               \
   V(InnerAllocatedObject)                      \
   V(InstanceOf)                                \
   V(InstanceOfKnownGlobal)                     \
@@ -135,7 +132,6 @@ class LChunkBuilder;
   V(IsSmiAndBranch)                            \
   V(IsUndetectableAndBranch)                   \
   V(LeaveInlined)                              \
-  V(LinkObjectInList)                          \
   V(LoadContextSlot)                           \
   V(LoadExternalArrayPointer)                  \
   V(LoadFieldByIndex)                          \
@@ -152,7 +148,6 @@ class LChunkBuilder;
   V(MathMinMax)                                \
   V(Mod)                                       \
   V(Mul)                                       \
-  V(NumericConstraint)                         \
   V(OsrEntry)                                  \
   V(OuterContext)                              \
   V(Parameter)                                 \
@@ -179,7 +174,6 @@ class LChunkBuilder;
   V(StringCharCodeAt)                          \
   V(StringCharFromCode)                        \
   V(StringCompareAndBranch)                    \
-  V(StringLength)                              \
   V(Sub)                                       \
   V(ThisFunction)                              \
   V(Throw)                                     \
@@ -201,6 +195,7 @@ class LChunkBuilder;
 #define GVN_UNTRACKED_FLAG_LIST(V)             \
   V(ArrayElements)                             \
   V(ArrayLengths)                              \
+  V(StringLengths)                             \
   V(BackingStoreFields)                        \
   V(Calls)                                     \
   V(ContextSlots)                              \
@@ -543,158 +538,6 @@ 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) {}
@@ -740,46 +583,6 @@ 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;
 
 
@@ -817,12 +620,6 @@ 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,
@@ -873,12 +670,13 @@ class HValue: public ZoneObject {
     HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
   #undef DECLARE_PREDICATE
 
-  HValue() : block_(NULL),
-             id_(kNoNumber),
-             type_(HType::Tagged()),
-             use_list_(NULL),
-             range_(NULL),
-             flags_(0) {}
+  HValue(HType type = HType::Tagged())
+      : block_(NULL),
+        id_(kNoNumber),
+        type_(type),
+        use_list_(NULL),
+        range_(NULL),
+        flags_(0) {}
   virtual ~HValue() {}
 
   HBasicBlock* block() const { return block_; }
@@ -959,8 +757,8 @@ class HValue: public ZoneObject {
     return RedefinedOperandIndex() != kNoRedefinedOperand;
   }
   HValue* RedefinedOperand() {
-    return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
-                                     : NULL;
+    int index = RedefinedOperandIndex();
+    return index == kNoRedefinedOperand ? NULL : OperandAt(index);
   }
 
   // A purely informative definition is an idef that will not emit code and
@@ -971,17 +769,8 @@ class HValue: public ZoneObject {
   // This method must always return the original HValue SSA definition
   // (regardless of any iDef of this value).
   HValue* ActualValue() {
-    return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
-                                     : this;
-  }
-
-  virtual void AddInformativeDefinitions() {}
-
-  void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
-    UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
-  }
-  void UpdateRedefinedUses() {
-    UpdateRedefinedUsesInner<Dominates>();
+    int index = RedefinedOperandIndex();
+    return index == kNoRedefinedOperand ? this : OperandAt(index);
   }
 
   bool IsInteger32Constant();
@@ -1132,12 +921,6 @@ 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);
@@ -1159,17 +942,6 @@ 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) {
@@ -1203,47 +975,6 @@ 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.
@@ -1308,6 +1039,48 @@ class HValue: public ZoneObject {
 };
 
 
+#define DECLARE_INSTRUCTION_FACTORY_P0(I)                                      \
+  static I* New(Zone* zone, HValue* context) {                                 \
+    return new(zone) I();                                                      \
+}
+
+#define DECLARE_INSTRUCTION_FACTORY_P1(I, P1)                                  \
+  static I* New(Zone* zone, HValue* context, P1 p1) {                          \
+    return new(zone) I(p1);                                                    \
+  }
+
+#define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2)                              \
+  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) {                   \
+    return new(zone) I(p1, p2);                                                \
+  }
+
+#define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3)                          \
+  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) {            \
+    return new(zone) I(p1, p2, p3);                                            \
+  }
+
+#define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4)                      \
+  static I* New(Zone* zone,                                                    \
+                HValue* context,                                               \
+                P1 p1,                                                         \
+                P2 p2,                                                         \
+                P3 p3,                                                         \
+                P4 p4) {                                                       \
+    return new(zone) I(p1, p2, p3, p4);                                        \
+  }
+
+#define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5)                  \
+  static I* New(Zone* zone,                                                    \
+                HValue* context,                                               \
+                P1 p1,                                                         \
+                P2 p2,                                                         \
+                P3 p3,                                                         \
+                P4 p4,                                                         \
+                P5 p5) {                                                       \
+    return new(zone) I(p1, p2, p3, p4, p5);                                    \
+  }
+
+
 class HInstruction: public HValue {
  public:
   HInstruction* next() const { return next_; }
@@ -1343,8 +1116,9 @@ class HInstruction: public HValue {
   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
 
  protected:
-  HInstruction()
-      : next_(NULL),
+  HInstruction(HType type = HType::Tagged())
+      : HValue(type),
+        next_(NULL),
         previous_(NULL),
         position_(RelocInfo::kNoPosition) {
     SetGVNFlag(kDependsOnOsrEntries);
@@ -1375,6 +1149,8 @@ class HTemplateInstruction : public HInstruction {
   HValue* OperandAt(int i) const { return inputs_[i]; }
 
  protected:
+  HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
+
   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
 
  private:
@@ -1448,12 +1224,12 @@ class HBlockEntry: public HTemplateInstruction<0> {
 
 class HDummyUse: public HTemplateInstruction<1> {
  public:
-  explicit HDummyUse(HValue* value) {
+  explicit HDummyUse(HValue* value)
+      : HTemplateInstruction<1>(HType::Smi()) {
     SetOperandAt(0, value);
     // Pretend to be a Smi so that the HChange instructions inserted
     // before any use generate as little code as possible.
     set_representation(Representation::Tagged());
-    set_type(HType::Smi());
   }
 
   HValue* value() { return OperandAt(0); }
@@ -1469,55 +1245,9 @@ 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:
-  explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
+  DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
@@ -1528,6 +1258,8 @@ class HDeoptimize: public HTemplateInstruction<0> {
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
 
  private:
+  explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
+
   Deoptimizer::BailoutType type_;
 };
 
@@ -1628,12 +1360,44 @@ class HCompareMap: public HUnaryControlInstruction {
 };
 
 
+class HContext: public HTemplateInstruction<0> {
+ public:
+  static HContext* New(Zone* zone) {
+    return new(zone) HContext();
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) {
+    return Representation::None();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Context)
+
+ protected:
+  virtual bool DataEquals(HValue* other) { return true; }
+
+ private:
+  HContext() {
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+  }
+
+  virtual bool IsDeletable() const { return true; }
+};
+
+
 class HReturn: public HTemplateControlInstruction<0, 3> {
  public:
-  HReturn(HValue* value, HValue* context, HValue* parameter_count) {
-    SetOperandAt(0, value);
-    SetOperandAt(1, context);
-    SetOperandAt(2, parameter_count);
+  static HInstruction* New(Zone* zone,
+                           HValue* context,
+                           HValue* value,
+                           HValue* parameter_count) {
+    return new(zone) HReturn(value, context, parameter_count);
+  }
+
+  static HInstruction* New(Zone* zone,
+                           HValue* context,
+                           HValue* value) {
+    return new(zone) HReturn(value, context, 0);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -1647,6 +1411,13 @@ class HReturn: public HTemplateControlInstruction<0, 3> {
   HValue* parameter_count() { return OperandAt(2); }
 
   DECLARE_CONCRETE_INSTRUCTION(Return)
+
+ private:
+  HReturn(HValue* value, HValue* context, HValue* parameter_count) {
+    SetOperandAt(0, value);
+    SetOperandAt(1, context);
+    SetOperandAt(2, parameter_count);
+  }
 };
 
 
@@ -1662,7 +1433,8 @@ class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
 
 class HUnaryOperation: public HTemplateInstruction<1> {
  public:
-  explicit HUnaryOperation(HValue* value) {
+  HUnaryOperation(HValue* value, HType type = HType::Tagged())
+      : HTemplateInstruction<1>(type) {
     SetOperandAt(0, value);
   }
 
@@ -1677,10 +1449,10 @@ class HUnaryOperation: public HTemplateInstruction<1> {
 
 class HThrow: public HTemplateInstruction<2> {
  public:
-  HThrow(HValue* context, HValue* value) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, value);
-    SetAllSideEffects();
+  static HThrow* New(Zone* zone,
+                     HValue* context,
+                     HValue* value) {
+    return new(zone) HThrow(context, value);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -1691,27 +1463,34 @@ class HThrow: public HTemplateInstruction<2> {
   HValue* value() { return OperandAt(1); }
 
   DECLARE_CONCRETE_INSTRUCTION(Throw)
+
+ private:
+  HThrow(HValue* context, HValue* value) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, value);
+    SetAllSideEffects();
+  }
 };
 
 
 class HUseConst: public HUnaryOperation {
  public:
-  explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
+  DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
   }
 
   DECLARE_CONCRETE_INSTRUCTION(UseConst)
+
+ private:
+    explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
 };
 
 
 class HForceRepresentation: public HTemplateInstruction<1> {
  public:
-  HForceRepresentation(HValue* value, Representation required_representation) {
-    SetOperandAt(0, value);
-    set_representation(required_representation);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P2(HForceRepresentation, HValue*, Representation);
 
   HValue* value() { return OperandAt(0); }
 
@@ -1724,6 +1503,12 @@ class HForceRepresentation: public HTemplateInstruction<1> {
   virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
+
+ private:
+  HForceRepresentation(HValue* value, Representation required_representation) {
+    SetOperandAt(0, value);
+    set_representation(required_representation);
+  }
 };
 
 
@@ -1785,12 +1570,7 @@ class HChange: public HUnaryOperation {
 
 class HClampToUint8: public HUnaryOperation {
  public:
-  explicit HClampToUint8(HValue* value)
-      : HUnaryOperation(value) {
-    set_representation(Representation::Integer32());
-    SetFlag(kAllowUndefinedAsNaN);
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
@@ -1802,6 +1582,13 @@ class HClampToUint8: public HUnaryOperation {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  explicit HClampToUint8(HValue* value)
+      : HUnaryOperation(value) {
+    set_representation(Representation::Integer32());
+    SetFlag(kAllowUndefinedAsNaN);
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -1958,10 +1745,7 @@ class HStackCheck: public HTemplateInstruction<1> {
     kBackwardsBranch
   };
 
-  HStackCheck(HValue* context, Type type) : type_(type) {
-    SetOperandAt(0, context);
-    SetGVNFlag(kChangesNewSpacePromotion);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P2(HStackCheck, HValue*, Type);
 
   HValue* context() { return OperandAt(0); }
 
@@ -1983,6 +1767,11 @@ class HStackCheck: public HTemplateInstruction<1> {
   DECLARE_CONCRETE_INSTRUCTION(StackCheck)
 
  private:
+  HStackCheck(HValue* context, Type type) : type_(type) {
+    SetOperandAt(0, context);
+    SetGVNFlag(kChangesNewSpacePromotion);
+  }
+
   Type type_;
 };
 
@@ -2001,23 +1790,18 @@ class HArgumentsObject;
 
 class HEnterInlined: public HTemplateInstruction<0> {
  public:
-  HEnterInlined(Handle<JSFunction> closure,
-                int arguments_count,
-                FunctionLiteral* function,
-                InliningKind inlining_kind,
-                Variable* arguments_var,
-                HArgumentsObject* arguments_object,
-                bool undefined_receiver,
-                Zone* zone)
-      : closure_(closure),
-        arguments_count_(arguments_count),
-        arguments_pushed_(false),
-        function_(function),
-        inlining_kind_(inlining_kind),
-        arguments_var_(arguments_var),
-        arguments_object_(arguments_object),
-        undefined_receiver_(undefined_receiver),
-        return_targets_(2, zone) {
+  static HEnterInlined* New(Zone* zone,
+                            HValue* context,
+                            Handle<JSFunction> closure,
+                            int arguments_count,
+                            FunctionLiteral* function,
+                            InliningKind inlining_kind,
+                            Variable* arguments_var,
+                            HArgumentsObject* arguments_object,
+                            bool undefined_receiver) {
+    return new(zone) HEnterInlined(closure, arguments_count, function,
+                                   inlining_kind, arguments_var,
+                                   arguments_object, undefined_receiver, zone);
   }
 
   void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
@@ -2043,6 +1827,25 @@ class HEnterInlined: public HTemplateInstruction<0> {
   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
 
  private:
+  HEnterInlined(Handle<JSFunction> closure,
+                int arguments_count,
+                FunctionLiteral* function,
+                InliningKind inlining_kind,
+                Variable* arguments_var,
+                HArgumentsObject* arguments_object,
+                bool undefined_receiver,
+                Zone* zone)
+      : closure_(closure),
+        arguments_count_(arguments_count),
+        arguments_pushed_(false),
+        function_(function),
+        inlining_kind_(inlining_kind),
+        arguments_var_(arguments_var),
+        arguments_object_(arguments_object),
+        undefined_receiver_(undefined_receiver),
+        return_targets_(2, zone) {
+  }
+
   Handle<JSFunction> closure_;
   int arguments_count_;
   bool arguments_pushed_;
@@ -2069,9 +1872,7 @@ class HLeaveInlined: public HTemplateInstruction<0> {
 
 class HPushArgument: public HUnaryOperation {
  public:
-  explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
-    set_representation(Representation::Tagged());
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HPushArgument, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -2080,6 +1881,11 @@ class HPushArgument: public HUnaryOperation {
   HValue* argument() { return OperandAt(0); }
 
   DECLARE_CONCRETE_INSTRUCTION(PushArgument)
+
+ private:
+  explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
+    set_representation(Representation::Tagged());
+  }
 };
 
 
@@ -2104,44 +1910,25 @@ class HThisFunction: public HTemplateInstruction<0> {
 };
 
 
-class HContext: public HTemplateInstruction<0> {
+class HOuterContext: public HUnaryOperation {
  public:
-  HContext() {
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HOuterContext, HValue*);
+
+  DECLARE_CONCRETE_INSTRUCTION(OuterContext);
 
   virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::None();
+    return Representation::Tagged();
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(Context)
-
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
-  virtual bool IsDeletable() const { return true; }
-};
-
-
-class HOuterContext: public HUnaryOperation {
- public:
   explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(OuterContext);
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Tagged();
-  }
-
- protected:
-  virtual bool DataEquals(HValue* other) { return true; }
-
- private:
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -2158,6 +1945,13 @@ class HDeclareGlobals: public HUnaryOperation {
     SetAllSideEffects();
   }
 
+  static HDeclareGlobals* New(Zone* zone,
+                              HValue* context,
+                              Handle<FixedArray> pairs,
+                              int flags) {
+    return new(zone) HDeclareGlobals(context, pairs, flags);
+  }
+
   HValue* context() { return OperandAt(0); }
   Handle<FixedArray> pairs() const { return pairs_; }
   int flags() const { return flags_; }
@@ -2167,6 +1961,7 @@ class HDeclareGlobals: public HUnaryOperation {
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
+
  private:
   Handle<FixedArray> pairs_;
   int flags_;
@@ -2180,6 +1975,10 @@ class HGlobalObject: public HUnaryOperation {
     SetFlag(kUseGVN);
   }
 
+  static HGlobalObject* New(Zone* zone, HValue* context) {
+    return new(zone) HGlobalObject(context);
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -2196,11 +1995,7 @@ class HGlobalObject: public HUnaryOperation {
 
 class HGlobalReceiver: public HUnaryOperation {
  public:
-  explicit HGlobalReceiver(HValue* global_object)
-      : HUnaryOperation(global_object) {
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HGlobalReceiver, HValue*);
 
   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
 
@@ -2212,6 +2007,12 @@ class HGlobalReceiver: public HUnaryOperation {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  explicit HGlobalReceiver(HValue* global_object)
+      : HUnaryOperation(global_object) {
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -2278,6 +2079,13 @@ class HInvokeFunction: public HBinaryCall {
       : HBinaryCall(context, function, argument_count) {
   }
 
+  static HInvokeFunction* New(Zone* zone,
+                              HValue* context,
+                              HValue* function,
+                              int argument_count) {
+    return new(zone) HInvokeFunction(context, function, argument_count);
+  }
+
   HInvokeFunction(HValue* context,
                   HValue* function,
                   Handle<JSFunction> known_function,
@@ -2288,6 +2096,15 @@ class HInvokeFunction: public HBinaryCall {
         ? 0 : known_function->shared()->formal_parameter_count();
   }
 
+  static HInvokeFunction* New(Zone* zone,
+                              HValue* context,
+                              HValue* function,
+                              Handle<JSFunction> known_function,
+                              int argument_count) {
+    return new(zone) HInvokeFunction(context, function,
+                                     known_function, argument_count);
+  }
+
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
@@ -2379,6 +2196,13 @@ class HCallFunction: public HBinaryCall {
       : HBinaryCall(context, function, argument_count) {
   }
 
+  static HCallFunction* New(Zone* zone,
+                            HValue* context,
+                            HValue* function,
+                            int argument_count) {
+    return new(zone) HCallFunction(context, function, argument_count);
+  }
+
   HValue* context() { return first(); }
   HValue* function() { return second(); }
 
@@ -2396,6 +2220,13 @@ class HCallGlobal: public HUnaryCall {
       : HUnaryCall(context, argument_count), name_(name) {
   }
 
+  static HCallGlobal* New(Zone* zone,
+                          HValue* context,
+                          Handle<String> name,
+                          int argument_count) {
+    return new(zone) HCallGlobal(context, name, argument_count);
+  }
+
   virtual void PrintDataTo(StringStream* stream);
 
   HValue* context() { return value(); }
@@ -2479,12 +2310,12 @@ class HCallNewArray: public HCallNew {
 
 class HCallRuntime: public HCall<1> {
  public:
-  HCallRuntime(HValue* context,
-               Handle<String> name,
-               const Runtime::Function* c_function,
-               int argument_count)
-      : HCall<1>(argument_count), c_function_(c_function), name_(name) {
-    SetOperandAt(0, context);
+  static HCallRuntime* New(Zone* zone,
+                           HValue* context,
+                           Handle<String> name,
+                           const Runtime::Function* c_function,
+                           int argument_count) {
+    return new(zone) HCallRuntime(context, name, c_function, argument_count);
   }
 
   virtual void PrintDataTo(StringStream* stream);
@@ -2500,6 +2331,14 @@ class HCallRuntime: public HCall<1> {
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
 
  private:
+  HCallRuntime(HValue* context,
+               Handle<String> name,
+               const Runtime::Function* c_function,
+               int argument_count)
+      : HCall<1>(argument_count), c_function_(c_function), name_(name) {
+    SetOperandAt(0, context);
+  }
+
   const Runtime::Function* c_function_;
   Handle<String> name_;
 };
@@ -2507,12 +2346,7 @@ class HCallRuntime: public HCall<1> {
 
 class HMapEnumLength: public HUnaryOperation {
  public:
-  explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) {
-    set_type(HType::Smi());
-    set_representation(Representation::Smi());
-    SetFlag(kUseGVN);
-    SetGVNFlag(kDependsOnMaps);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -2524,6 +2358,13 @@ class HMapEnumLength: public HUnaryOperation {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  explicit HMapEnumLength(HValue* value)
+      : HUnaryOperation(value, HType::Smi()) {
+    set_representation(Representation::Smi());
+    SetFlag(kUseGVN);
+    SetGVNFlag(kDependsOnMaps);
+  }
+
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -2550,35 +2391,6 @@ class HElementsKind: public HUnaryOperation {
 };
 
 
-class HBitNot: public HUnaryOperation {
- public:
-  explicit HBitNot(HValue* value) : HUnaryOperation(value) {
-    set_representation(Representation::Integer32());
-    SetFlag(kUseGVN);
-    SetFlag(kTruncatingToInt32);
-    SetFlag(kAllowUndefinedAsNaN);
-  }
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Integer32();
-  }
-  virtual Representation observed_input_representation(int index) {
-    return Representation::Integer32();
-  }
-  virtual HType CalculateInferredType();
-
-  virtual HValue* Canonicalize();
-
-  DECLARE_CONCRETE_INSTRUCTION(BitNot)
-
- protected:
-  virtual bool DataEquals(HValue* other) { return true; }
-
- private:
-  virtual bool IsDeletable() const { return true; }
-};
-
-
 class HUnaryMathOperation: public HTemplateInstruction<2> {
  public:
   static HInstruction* New(Zone* zone,
@@ -2591,8 +2403,6 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
 
   virtual void PrintDataTo(StringStream* stream);
 
-  virtual HType CalculateInferredType();
-
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -2637,7 +2447,7 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
 
  private:
   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
-      : op_(op) {
+      : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
     SetOperandAt(0, context);
     SetOperandAt(1, value);
     switch (op) {
@@ -2681,15 +2491,7 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
 
 class HLoadExternalArrayPointer: public HUnaryOperation {
  public:
-  explicit HLoadExternalArrayPointer(HValue* value)
-      : HUnaryOperation(value) {
-    set_representation(Representation::External());
-    // The result of this instruction is idempotent as long as its inputs don't
-    // change.  The external array of a specialized array elements object cannot
-    // change once set, so it's no necessary to introduce any additional
-    // dependencies on top of the inputs.
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HLoadExternalArrayPointer, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -2705,27 +2507,37 @@ class HLoadExternalArrayPointer: public HUnaryOperation {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  explicit HLoadExternalArrayPointer(HValue* value)
+      : HUnaryOperation(value) {
+    set_representation(Representation::External());
+    // The result of this instruction is idempotent as long as its inputs don't
+    // change.  The external array of a specialized array elements object cannot
+    // change once set, so it's no necessary to introduce any additional
+    // dependencies on top of the inputs.
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const { return true; }
 };
 
 
 class HCheckMaps: public HTemplateInstruction<2> {
  public:
-  static HCheckMaps* New(HValue* value, Handle<Map> map, Zone* zone,
-                         CompilationInfo* info, HValue *typecheck = NULL);
-  static HCheckMaps* New(HValue* value, SmallMapList* maps, Zone* zone,
+  static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
+                         Handle<Map> map, CompilationInfo* info,
+                         HValue *typecheck = NULL);
+  static HCheckMaps* New(Zone* zone, HValue* context,
+                         HValue* value, SmallMapList* maps,
                          HValue *typecheck = NULL) {
     HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
     for (int i = 0; i < maps->length(); i++) {
       check_map->map_set_.Add(maps->at(i), zone);
+      check_map->has_migration_target_ |= maps->at(i)->is_migration_target();
     }
     check_map->map_set_.Sort();
     return check_map;
   }
 
-  static HCheckMaps* NewWithTransitions(HValue* value, Handle<Map> map,
-                                        Zone* zone, CompilationInfo* info);
-
   bool CanOmitMapChecks() { return omit_; }
 
   virtual bool HasEscapingOperandAt(int index) { return false; }
@@ -2735,11 +2547,14 @@ class HCheckMaps: public HTemplateInstruction<2> {
   virtual void HandleSideEffectDominator(GVNFlag side_effect,
                                          HValue* dominator);
   virtual void PrintDataTo(StringStream* stream);
-  virtual HType CalculateInferredType();
 
   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)
@@ -2763,7 +2578,8 @@ class HCheckMaps: public HTemplateInstruction<2> {
  private:
   // Clients should use one of the static New* methods above.
   HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
-      : omit_(false), map_unique_ids_(0, zone) {
+      : HTemplateInstruction<2>(value->type()),
+        omit_(false), has_migration_target_(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?
@@ -2785,6 +2601,7 @@ class HCheckMaps: public HTemplateInstruction<2> {
   }
 
   bool omit_;
+  bool has_migration_target_;
   SmallMapList map_set_;
   ZoneList<UniqueValueId> map_unique_ids_;
 };
@@ -2792,18 +2609,12 @@ class HCheckMaps: public HTemplateInstruction<2> {
 
 class HCheckFunction: public HUnaryOperation {
  public:
-  HCheckFunction(HValue* value, Handle<JSFunction> function)
-      : HUnaryOperation(value), target_(function), target_unique_id_() {
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-    target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P2(HCheckFunction, HValue*, Handle<JSFunction>);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
   virtual void PrintDataTo(StringStream* stream);
-  virtual HType CalculateInferredType();
 
   virtual HValue* Canonicalize();
 
@@ -2827,6 +2638,14 @@ class HCheckFunction: public HUnaryOperation {
   }
 
  private:
+  HCheckFunction(HValue* value, Handle<JSFunction> function)
+      : HUnaryOperation(value, value->type()),
+        target_(function), target_unique_id_() {
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+    target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
+  }
+
   Handle<JSFunction> target_;
   UniqueValueId target_unique_id_;
   bool target_in_new_space_;
@@ -2895,17 +2714,12 @@ class HCheckInstanceType: public HUnaryOperation {
 
 class HCheckSmi: public HUnaryOperation {
  public:
-  explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
-    set_representation(Representation::Smi());
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType();
-
   virtual HValue* Canonicalize() {
     HType value_type = value()->type();
     if (value_type.IsSmi()) {
@@ -2918,6 +2732,12 @@ class HCheckSmi: public HUnaryOperation {
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
+
+ private:
+  explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
+    set_representation(Representation::Smi());
+    SetFlag(kUseGVN);
+  }
 };
 
 
@@ -2938,17 +2758,12 @@ class HIsNumberAndBranch: public HUnaryControlInstruction {
 
 class HCheckHeapObject: public HUnaryOperation {
  public:
-  explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType();
-
 #ifdef DEBUG
   virtual void Verify();
 #endif
@@ -2961,79 +2776,13 @@ class HCheckHeapObject: public HUnaryOperation {
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
-};
-
 
-class HCheckPrototypeMaps: public HTemplateInstruction<0> {
- public:
-  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) {
+ private:
+  explicit HCheckHeapObject(HValue* value)
+      : HUnaryOperation(value, HType::NonPrimitive()) {
+    set_representation(Representation::Tagged());
     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() { 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:
-  ZoneList<Handle<JSObject> > prototypes_;
-  ZoneList<Handle<Map> > maps_;
-  UniqueValueId first_prototype_unique_id_;
-  UniqueValueId last_prototype_unique_id_;
-  bool can_omit_prototype_maps_;
 };
 
 
@@ -3310,8 +3059,6 @@ class HPhi: public HValue {
     induction_variable_data_ = InductionVariableData::ExaminePhi(this);
   }
 
-  virtual void AddInformativeDefinitions();
-
   virtual void PrintTo(StringStream* stream);
 
 #ifdef DEBUG
@@ -3362,11 +3109,6 @@ 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_;
@@ -3381,58 +3123,12 @@ class HPhi: public HValue {
 };
 
 
-class HInductionVariableAnnotation : public HUnaryOperation {
- public:
-  static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
-                                                  NumericRelation relation,
-                                                  int operand_index);
-
-  NumericRelation relation() { return relation_; }
-  HValue* induction_base() { return phi_->OperandAt(operand_index_); }
-
-  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 (induction_base() == other_related_value) {
-      return relation().CompoundImplies(other_relation, offset, scale);
-    } else {
-      return false;
-    }
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation)
-
- private:
-  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 HTemplateInstruction<0> {
  public:
-  HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
-    set_representation(Representation::Tagged());
-    SetFlag(kIsArguments);
+  static HArgumentsObject* New(Zone* zone,
+                               HValue* context,
+                               int count) {
+    return new(zone) HArgumentsObject(count, zone);
   }
 
   const ZoneList<HValue*>* arguments_values() const { return &values_; }
@@ -3459,6 +3155,11 @@ class HArgumentsObject: public HTemplateInstruction<0> {
   }
 
  private:
+  HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
+    set_representation(Representation::Tagged());
+    SetFlag(kIsArguments);
+  }
+
   virtual bool IsDeletable() const { return true; }
 
   ZoneList<HValue*> values_;
@@ -3467,24 +3168,11 @@ class HArgumentsObject: public HTemplateInstruction<0> {
 
 class HConstant: public HTemplateInstruction<0> {
  public:
-  HConstant(Handle<Object> handle, Representation r = Representation::None());
-  HConstant(int32_t value,
-            Representation r = Representation::None(),
-            bool is_not_in_new_space = true,
-            Handle<Object> optional_handle = Handle<Object>::null());
-  HConstant(double value,
-            Representation r = Representation::None(),
-            bool is_not_in_new_space = true,
-            Handle<Object> optional_handle = Handle<Object>::null());
-  HConstant(Handle<Object> handle,
-            UniqueValueId unique_id,
-            Representation r,
-            HType type,
-            bool is_internalized_string,
-            bool is_not_in_new_space,
-            bool is_cell,
-            bool boolean_value);
-  explicit HConstant(ExternalReference reference);
+  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
+  DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
+  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
+  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
+  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
 
   Handle<Object> handle() {
     if (handle_.is_null()) {
@@ -3524,6 +3212,9 @@ class HConstant: public HTemplateInstruction<0> {
       }
       return false;
     }
+    if (has_external_reference_value_) {
+      return false;
+    }
 
     ASSERT(!handle_.is_null());
     Heap* heap = isolate()->heap();
@@ -3665,6 +3356,26 @@ class HConstant: public HTemplateInstruction<0> {
   }
 
  private:
+  friend class HGraph;
+  HConstant(Handle<Object> handle, Representation r = Representation::None());
+  HConstant(int32_t value,
+            Representation r = Representation::None(),
+            bool is_not_in_new_space = true,
+            Handle<Object> optional_handle = Handle<Object>::null());
+  HConstant(double value,
+            Representation r = Representation::None(),
+            bool is_not_in_new_space = true,
+            Handle<Object> optional_handle = Handle<Object>::null());
+  HConstant(Handle<Object> handle,
+            UniqueValueId unique_id,
+            Representation r,
+            HType type,
+            bool is_internalized_string,
+            bool is_not_in_new_space,
+            bool is_cell,
+            bool boolean_value);
+  explicit HConstant(ExternalReference reference);
+
   void Initialize(Representation r);
 
   virtual bool IsDeletable() const { return true; }
@@ -3697,8 +3408,10 @@ class HConstant: public HTemplateInstruction<0> {
 
 class HBinaryOperation: public HTemplateInstruction<3> {
  public:
-  HBinaryOperation(HValue* context, HValue* left, HValue* right)
-      : observed_output_representation_(Representation::None()) {
+  HBinaryOperation(HValue* context, HValue* left, HValue* right,
+                   HType type = HType::Tagged())
+      : HTemplateInstruction<3>(type),
+        observed_output_representation_(Representation::None()) {
     ASSERT(left != NULL && right != NULL);
     SetOperandAt(0, context);
     SetOperandAt(1, left);
@@ -3782,11 +3495,7 @@ class HBinaryOperation: public HTemplateInstruction<3> {
 
 class HWrapReceiver: public HTemplateInstruction<2> {
  public:
-  HWrapReceiver(HValue* receiver, HValue* function) {
-    set_representation(Representation::Tagged());
-    SetOperandAt(0, receiver);
-    SetOperandAt(1, function);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -3800,13 +3509,20 @@ class HWrapReceiver: public HTemplateInstruction<2> {
   virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
-};
-
 
-class HApplyArguments: public HTemplateInstruction<4> {
- public:
-  HApplyArguments(HValue* function,
-                  HValue* receiver,
+ private:
+  HWrapReceiver(HValue* receiver, HValue* function) {
+    set_representation(Representation::Tagged());
+    SetOperandAt(0, receiver);
+    SetOperandAt(1, function);
+  }
+};
+
+
+class HApplyArguments: public HTemplateInstruction<4> {
+ public:
+  HApplyArguments(HValue* function,
+                  HValue* receiver,
                   HValue* length,
                   HValue* elements) {
     set_representation(Representation::Tagged());
@@ -3835,12 +3551,7 @@ class HApplyArguments: public HTemplateInstruction<4> {
 
 class HArgumentsElements: public HTemplateInstruction<0> {
  public:
-  explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
-    // The value produced by this instruction is a pointer into the stack
-    // that looks as if it was a smi because of alignment.
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
 
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
 
@@ -3854,6 +3565,13 @@ class HArgumentsElements: public HTemplateInstruction<0> {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
+    // The value produced by this instruction is a pointer into the stack
+    // that looks as if it was a smi because of alignment.
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const { return true; }
 
   bool from_inlined_;
@@ -3862,10 +3580,7 @@ class HArgumentsElements: public HTemplateInstruction<0> {
 
 class HArgumentsLength: public HUnaryOperation {
  public:
-  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
-    set_representation(Representation::Integer32());
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -3877,6 +3592,11 @@ class HArgumentsLength: public HUnaryOperation {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
+    set_representation(Representation::Integer32());
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -3915,32 +3635,14 @@ class HBoundsCheckBaseIndexInformation;
 
 class HBoundsCheck: public HTemplateInstruction<2> {
  public:
-  // Normally HBoundsCheck should be created using the
-  // HGraphBuilder::AddBoundsCheck() helper.
-  // However when building stubs, where we know that the arguments are Int32,
-  // it makes sense to invoke this constructor directly.
-  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);
-    SetFlag(kFlexibleRepresentation);
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
 
   bool skip_check() const { return skip_check_; }
   void set_skip_check() { skip_check_ = true; }
+
   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() {
@@ -3964,11 +3666,6 @@ 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);
 
@@ -3979,28 +3676,34 @@ 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:
+  // Normally HBoundsCheck should be created using the
+  // HGraphBuilder::AddBoundsCheck() helper.
+  // However when building stubs, where we know that the arguments are Int32,
+  // it makes sense to invoke this constructor directly.
+  HBoundsCheck(HValue* index, HValue* length)
+    : skip_check_(false),
+      base_(NULL), offset_(0), scale_(0),
+      allow_equality_(false) {
+    SetOperandAt(0, index);
+    SetOperandAt(1, length);
+    SetFlag(kFlexibleRepresentation);
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const {
     return skip_check() && !FLAG_debug_code;
   }
@@ -4028,29 +3731,18 @@ 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);
-  }
 };
 
 
 class HBitwiseBinaryOperation: public HBinaryOperation {
  public:
-  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
-      : HBinaryOperation(context, left, right) {
+  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
+                          HType type = HType::Tagged())
+      : HBinaryOperation(context, left, right, type) {
     SetFlag(kFlexibleRepresentation);
     SetFlag(kTruncatingToInt32);
     SetFlag(kAllowUndefinedAsNaN);
@@ -4087,8 +3779,6 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
     HBinaryOperation::initialize_output_representation(observed);
   }
 
-  virtual HType CalculateInferredType();
-
   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
 
  private:
@@ -4098,15 +3788,11 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
 
 class HMathFloorOfDiv: public HBinaryOperation {
  public:
-  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
-      : HBinaryOperation(context, left, right) {
-    set_representation(Representation::Integer32());
-    SetFlag(kUseGVN);
-    SetFlag(kCanOverflow);
-    if (!right->IsConstant()) {
-      SetFlag(kCanBeDivByZero);
-    }
-    SetFlag(kAllowUndefinedAsNaN);
+  static HMathFloorOfDiv* New(Zone* zone,
+                              HValue* context,
+                              HValue* left,
+                              HValue* right) {
+    return new(zone) HMathFloorOfDiv(context, left, right);
   }
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
@@ -4121,6 +3807,17 @@ class HMathFloorOfDiv: public HBinaryOperation {
   virtual bool DataEquals(HValue* other) { return true; }
 
  private:
+  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
+      : HBinaryOperation(context, left, right) {
+    set_representation(Representation::Integer32());
+    SetFlag(kUseGVN);
+    SetFlag(kCanOverflow);
+    if (!right->IsConstant()) {
+      SetFlag(kCanBeDivByZero);
+    }
+    SetFlag(kAllowUndefinedAsNaN);
+  }
+
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -4128,7 +3825,7 @@ class HMathFloorOfDiv: public HBinaryOperation {
 class HArithmeticBinaryOperation: public HBinaryOperation {
  public:
   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
-      : HBinaryOperation(context, left, right) {
+      : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
     SetAllSideEffects();
     SetFlag(kFlexibleRepresentation);
     SetFlag(kAllowUndefinedAsNaN);
@@ -4144,8 +3841,6 @@ class HArithmeticBinaryOperation: public HBinaryOperation {
     }
   }
 
-  virtual HType CalculateInferredType();
-
   DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
 
  private:
@@ -4159,7 +3854,8 @@ class HCompareGeneric: public HBinaryOperation {
                   HValue* left,
                   HValue* right,
                   Token::Value token)
-      : HBinaryOperation(context, left, right), token_(token) {
+      : HBinaryOperation(context, left, right, HType::Boolean()),
+        token_(token) {
     ASSERT(Token::IsCompareOp(token));
     set_representation(Representation::Tagged());
     SetAllSideEffects();
@@ -4174,8 +3870,6 @@ class HCompareGeneric: public HBinaryOperation {
   Token::Value token() const { return token_; }
   virtual void PrintDataTo(StringStream* stream);
 
-  virtual HType CalculateInferredType();
-
   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
 
  private:
@@ -4213,8 +3907,6 @@ class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
   }
   virtual void PrintDataTo(StringStream* stream);
 
-  virtual void AddInformativeDefinitions();
-
   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
 
  private:
@@ -4225,11 +3917,16 @@ class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
 
 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
  public:
-  HCompareObjectEqAndBranch(HValue* left, HValue* right) {
+  // TODO(danno): make this private when the IfBuilder properly constructs
+  // control flow instructions.
+  HCompareObjectEqAndBranch(HValue* left,
+                            HValue* right) {
     SetOperandAt(0, left);
     SetOperandAt(1, right);
   }
 
+  DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
+
   HValue* left() { return OperandAt(0); }
   HValue* right() { return OperandAt(1); }
 
@@ -4451,7 +4148,7 @@ class HTypeofIsAndBranch: public HUnaryControlInstruction {
 class HInstanceOf: public HBinaryOperation {
  public:
   HInstanceOf(HValue* context, HValue* left, HValue* right)
-      : HBinaryOperation(context, left, right) {
+      : HBinaryOperation(context, left, right, HType::Boolean()) {
     set_representation(Representation::Tagged());
     SetAllSideEffects();
   }
@@ -4460,8 +4157,6 @@ class HInstanceOf: public HBinaryOperation {
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType();
-
   virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
@@ -4473,7 +4168,7 @@ class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
   HInstanceOfKnownGlobal(HValue* context,
                          HValue* left,
                          Handle<JSFunction> right)
-      : function_(right) {
+      : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
     SetOperandAt(0, context);
     SetOperandAt(1, left);
     set_representation(Representation::Tagged());
@@ -4488,8 +4183,6 @@ class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType();
-
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
 
  private:
@@ -4519,7 +4212,10 @@ class HInstanceSize: public HTemplateInstruction<1> {
 
 class HPower: public HTemplateInstruction<2> {
  public:
-  static HInstruction* New(Zone* zone, HValue* left, HValue* right);
+  static HInstruction* New(Zone* zone,
+                           HValue* context,
+                           HValue* left,
+                           HValue* right);
 
   HValue* left() { return OperandAt(0); }
   HValue* right() const { return OperandAt(1); }
@@ -4588,8 +4284,6 @@ class HAdd: public HArithmeticBinaryOperation {
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
 
-  virtual HType CalculateInferredType();
-
   virtual HValue* Canonicalize();
 
   virtual bool TryDecompose(DecompositionResult* decomposition) {
@@ -4856,8 +4550,8 @@ class HMathMinMax: public HArithmeticBinaryOperation {
 class HBitwise: public HBitwiseBinaryOperation {
  public:
   static HInstruction* New(Zone* zone,
-                           Token::Value op,
                            HValue* context,
+                           Token::Value op,
                            HValue* left,
                            HValue* right);
 
@@ -4879,8 +4573,12 @@ class HBitwise: public HBitwiseBinaryOperation {
   virtual Range* InferRange(Zone* zone);
 
  private:
-  HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
-      : HBitwiseBinaryOperation(context, left, right), op_(op) {
+  HBitwise(HValue* context,
+           Token::Value op,
+           HValue* left,
+           HValue* right)
+      : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()),
+        op_(op) {
     ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
     // BIT_AND with a smi-range positive value will always unset the
     // entire sign-extension of the smi-sign.
@@ -5041,10 +4739,7 @@ class HRor: public HBitwiseBinaryOperation {
 
 class HOsrEntry: public HTemplateInstruction<0> {
  public:
-  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
-    SetGVNFlag(kChangesOsrEntries);
-    SetGVNFlag(kChangesNewSpacePromotion);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
 
   BailoutId ast_id() const { return ast_id_; }
 
@@ -5055,6 +4750,11 @@ class HOsrEntry: public HTemplateInstruction<0> {
   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
 
  private:
+  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
+    SetGVNFlag(kChangesOsrEntries);
+    SetGVNFlag(kChangesNewSpacePromotion);
+  }
+
   BailoutId ast_id_;
 };
 
@@ -5066,6 +4766,23 @@ class HParameter: public HTemplateInstruction<0> {
     REGISTER_PARAMETER
   };
 
+  DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
+  DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
+  DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
+                                 Representation);
+
+  unsigned index() const { return index_; }
+  ParameterKind kind() const { return kind_; }
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  virtual Representation RequiredInputRepresentation(int index) {
+    return Representation::None();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Parameter)
+
+ private:
   explicit HParameter(unsigned index,
                       ParameterKind kind = STACK_PARAMETER)
       : index_(index),
@@ -5081,18 +4798,6 @@ class HParameter: public HTemplateInstruction<0> {
     set_representation(r);
   }
 
-  unsigned index() const { return index_; }
-  ParameterKind kind() const { return kind_; }
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::None();
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(Parameter)
-
- private:
   unsigned index_;
   ParameterKind kind_;
 };
@@ -5133,10 +4838,7 @@ class HCallStub: public HUnaryCall {
 
 class HUnknownOSRValue: public HTemplateInstruction<0> {
  public:
-  HUnknownOSRValue()
-      : incoming_value_(NULL) {
-    set_representation(Representation::Tagged());
-  }
+  DECLARE_INSTRUCTION_FACTORY_P0(HUnknownOSRValue)
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
@@ -5158,6 +4860,11 @@ class HUnknownOSRValue: public HTemplateInstruction<0> {
   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
 
  private:
+  HUnknownOSRValue()
+      : incoming_value_(NULL) {
+    set_representation(Representation::Tagged());
+  }
+
   HPhi* incoming_value_;
 };
 
@@ -5240,41 +4947,19 @@ class HLoadGlobalGeneric: public HTemplateInstruction<2> {
 
 class HAllocate: public HTemplateInstruction<2> {
  public:
-  enum Flags {
-    CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0,
-    CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
-    CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
-    ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
-    PREFILL_WITH_FILLER = 1 << 4
-  };
-
-  HAllocate(HValue* context, HValue* size, HType type, Flags flags)
-      : flags_(flags) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, size);
-    set_type(type);
-    set_representation(Representation::Tagged());
-    SetFlag(kTrackSideEffectDominators);
-    SetGVNFlag(kChangesNewSpacePromotion);
-    SetGVNFlag(kDependsOnNewSpacePromotion);
+  static HAllocate* New(Zone* zone,
+                        HValue* context,
+                        HValue* size,
+                        HType type,
+                        PretenureFlag pretenure_flag,
+                        InstanceType instance_type) {
+    return new(zone) HAllocate(context, size, type, pretenure_flag,
+        instance_type);
   }
 
   // Maximum instance size for which allocations will be inlined.
   static const int kMaxInlineSize = 64 * kPointerSize;
 
-  static Flags DefaultFlags() {
-    return CAN_ALLOCATE_IN_NEW_SPACE;
-  }
-
-  static Flags DefaultFlags(ElementsKind kind) {
-    Flags flags = CAN_ALLOCATE_IN_NEW_SPACE;
-    if (IsFastDoubleElementsKind(kind)) {
-      flags = static_cast<HAllocate::Flags>(
-          flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED);
-    }
-    return flags;
-  }
-
   HValue* context() { return OperandAt(0); }
   HValue* size() { return OperandAt(1); }
 
@@ -5294,25 +4979,16 @@ class HAllocate: public HTemplateInstruction<2> {
     known_initial_map_ = known_initial_map;
   }
 
-  bool CanAllocateInNewSpace() const {
-    return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0;
-  }
-
-  bool CanAllocateInOldDataSpace() const {
-    return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0;
-  }
-
-  bool CanAllocateInOldPointerSpace() const {
-    return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
+  bool IsNewSpaceAllocation() const {
+    return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
   }
 
-  bool CanAllocateInOldSpace() const {
-    return CanAllocateInOldDataSpace() ||
-        CanAllocateInOldPointerSpace();
+  bool IsOldDataSpaceAllocation() const {
+    return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
   }
 
-  bool GuaranteedInNewSpace() const {
-    return CanAllocateInNewSpace() && !CanAllocateInOldSpace();
+  bool IsOldPointerSpaceAllocation() const {
+    return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
   }
 
   bool MustAllocateDoubleAligned() const {
@@ -5323,8 +4999,12 @@ class HAllocate: public HTemplateInstruction<2> {
     return (flags_ & PREFILL_WITH_FILLER) != 0;
   }
 
-  void SetFlags(Flags flags) {
-    flags_ = static_cast<HAllocate::Flags>(flags_ | flags);
+  void MakePrefillWithFiller() {
+    flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
+  }
+
+  void MakeDoubleAligned() {
+    flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
   }
 
   void UpdateSize(HValue* size) {
@@ -5339,6 +5019,36 @@ class HAllocate: public HTemplateInstruction<2> {
   DECLARE_CONCRETE_INSTRUCTION(Allocate)
 
  private:
+  enum Flags {
+    ALLOCATE_IN_NEW_SPACE = 1 << 0,
+    ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
+    ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
+    ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
+    PREFILL_WITH_FILLER = 1 << 4
+  };
+
+  HAllocate(HValue* context,
+            HValue* size,
+            HType type,
+            PretenureFlag pretenure_flag,
+            InstanceType instance_type)
+      : HTemplateInstruction<2>(type) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, size);
+    set_representation(Representation::Tagged());
+    SetFlag(kTrackSideEffectDominators);
+    SetGVNFlag(kChangesNewSpacePromotion);
+    SetGVNFlag(kDependsOnNewSpacePromotion);
+    flags_ = pretenure_flag == TENURED
+        ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
+            ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
+        : ALLOCATE_IN_NEW_SPACE;
+    if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
+      flags_ = static_cast<HAllocate::Flags>(flags_ |
+          ALLOCATE_DOUBLE_ALIGNED);
+    }
+  }
+
   Flags flags_;
   Handle<Map> known_initial_map_;
 };
@@ -5346,12 +5056,12 @@ class HAllocate: public HTemplateInstruction<2> {
 
 class HInnerAllocatedObject: public HTemplateInstruction<1> {
  public:
-  HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
-      : offset_(offset) {
-    ASSERT(value->IsAllocate());
-    SetOperandAt(0, value);
-    set_type(type);
-    set_representation(Representation::Tagged());
+  static HInnerAllocatedObject* New(Zone* zone,
+                                    HValue* context,
+                                    HValue* value,
+                                    int offset,
+                                    HType type = HType::Tagged()) {
+    return new(zone) HInnerAllocatedObject(value, offset, type);
   }
 
   HValue* base_object() { return OperandAt(0); }
@@ -5366,6 +5076,14 @@ class HInnerAllocatedObject: public HTemplateInstruction<1> {
   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
 
  private:
+  HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
+      : HTemplateInstruction<1>(type), offset_(offset) {
+    ASSERT(value->IsAllocate());
+    SetOperandAt(0, value);
+    set_type(type);
+    set_representation(Representation::Tagged());
+  }
+
   int offset_;
 };
 
@@ -5387,9 +5105,14 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
   if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
     return false;
   }
+  if (object->IsConstant() &&
+      HConstant::cast(object)->HasExternalReferenceValue()) {
+    // Stores to external references require no write barriers
+    return false;
+  }
   if (object != new_space_dominator) return true;
   if (object->IsAllocate()) {
-    return !HAllocate::cast(object)->GuaranteedInNewSpace();
+    return !HAllocate::cast(object)->IsNewSpaceAllocation();
   }
   return true;
 }
@@ -5397,14 +5120,8 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
 
 class HStoreGlobalCell: public HUnaryOperation {
  public:
-  HStoreGlobalCell(HValue* value,
-                   Handle<PropertyCell> cell,
-                   PropertyDetails details)
-      : HUnaryOperation(value),
-        cell_(cell),
-        details_(details) {
-    SetGVNFlag(kChangesGlobalVars);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
+                                 Handle<PropertyCell>, PropertyDetails);
 
   Handle<PropertyCell> cell() const { return cell_; }
   bool RequiresHoleCheck() {
@@ -5422,6 +5139,15 @@ class HStoreGlobalCell: public HUnaryOperation {
   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
 
  private:
+  HStoreGlobalCell(HValue* value,
+                   Handle<PropertyCell> cell,
+                   PropertyDetails details)
+      : HUnaryOperation(value),
+        cell_(cell),
+        details_(details) {
+    SetGVNFlag(kChangesGlobalVars);
+  }
+
   Handle<PropertyCell> cell_;
   PropertyDetails details_;
 };
@@ -5429,18 +5155,14 @@ class HStoreGlobalCell: public HUnaryOperation {
 
 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
  public:
-  HStoreGlobalGeneric(HValue* context,
-                      HValue* global_object,
-                      Handle<Object> name,
-                      HValue* value,
-                      StrictModeFlag strict_mode_flag)
-      : name_(name),
-        strict_mode_flag_(strict_mode_flag) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, global_object);
-    SetOperandAt(2, value);
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
+  inline static HStoreGlobalGeneric* New(Zone* zone,
+                                         HValue* context,
+                                         HValue* global_object,
+                                         Handle<Object> name,
+                                         HValue* value,
+                                         StrictModeFlag strict_mode_flag) {
+    return new(zone) HStoreGlobalGeneric(context, global_object,
+                                         name, value, strict_mode_flag);
   }
 
   HValue* context() { return OperandAt(0); }
@@ -5458,6 +5180,20 @@ class HStoreGlobalGeneric: public HTemplateInstruction<3> {
   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
 
  private:
+  HStoreGlobalGeneric(HValue* context,
+                      HValue* global_object,
+                      Handle<Object> name,
+                      HValue* value,
+                      StrictModeFlag strict_mode_flag)
+      : name_(name),
+        strict_mode_flag_(strict_mode_flag) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, global_object);
+    SetOperandAt(2, value);
+    set_representation(Representation::Tagged());
+    SetAllSideEffects();
+  }
+
   Handle<Object> name_;
   StrictModeFlag strict_mode_flag_;
 };
@@ -5545,12 +5281,8 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
     kCheckIgnoreAssignment
   };
 
-  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
-      : slot_index_(slot_index), mode_(mode) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, value);
-    SetGVNFlag(kChangesContextSlots);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
+                                 Mode, HValue*);
 
   HValue* context() { return OperandAt(0); }
   HValue* value() { return OperandAt(1); }
@@ -5578,6 +5310,13 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
 
  private:
+  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
+      : slot_index_(slot_index), mode_(mode) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, value);
+    SetGVNFlag(kChangesContextSlots);
+  }
+
   int slot_index_;
   Mode mode_;
 };
@@ -5595,6 +5334,10 @@ class HObjectAccess {
     return portion() == kExternalMemory;
   }
 
+  inline bool IsStringLength() const {
+    return portion() == kStringLengths;
+  }
+
   inline int offset() const {
     return OffsetField::decode(value_);
   }
@@ -5637,6 +5380,10 @@ class HObjectAccess {
     return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset);
   }
 
+  static HObjectAccess ForAllocationSiteList() {
+    return HObjectAccess(kExternalMemory, 0, Representation::Tagged());
+  }
+
   static HObjectAccess ForFixedArrayLength() {
     return HObjectAccess(
         kArrayLengths,
@@ -5644,6 +5391,14 @@ class HObjectAccess {
         FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
   }
 
+  static HObjectAccess ForStringLength() {
+    STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
+    return HObjectAccess(
+        kStringLengths,
+        String::kLengthOffset,
+        FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
+  }
+
   static HObjectAccess ForPropertiesPointer() {
     return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
   }
@@ -5707,6 +5462,7 @@ class HObjectAccess {
   enum Portion {
     kMaps,             // map of an object
     kArrayLengths,     // the length of an array
+    kStringLengths,    // the length of a string
     kElementsPointer,  // elements pointer
     kBackingStore,     // some field in the backing store
     kDouble,           // some double field
@@ -5743,40 +5499,44 @@ class HObjectAccess {
 };
 
 
-class HLinkObjectInList: public HUnaryOperation {
+class HLoadNamedField: public HTemplateInstruction<2> {
  public:
-  // There needs to be a mapping from every KnownList to an external reference
-  enum KnownList {
-    ALLOCATION_SITE_LIST
-  };
+  DECLARE_INSTRUCTION_FACTORY_P2(HLoadNamedField, HValue*, HObjectAccess);
+  DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HObjectAccess,
+                                 HValue*);
 
-  HLinkObjectInList(HValue* object, HObjectAccess store_field,
-                    KnownList known_list)
-      : HUnaryOperation(object),
-        store_field_(store_field),
-        known_list_(known_list) {
-    set_representation(Representation::Tagged());
+  HValue* object() { return OperandAt(0); }
+  HValue* typecheck() {
+    ASSERT(HasTypeCheck());
+    return OperandAt(1);
   }
 
-  HObjectAccess store_field() const { return store_field_; }
-  KnownList known_list() const { return known_list_; }
+  bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
+  HObjectAccess access() const { return access_; }
+  Representation field_representation() const {
+      return access_.representation();
+  }
 
+  virtual bool HasEscapingOperandAt(int index) { return false; }
   virtual Representation RequiredInputRepresentation(int index) {
+    if (index == 0 && access().IsExternalMemory()) {
+      // object must be external in case of external memory access
+      return Representation::External();
+    }
     return Representation::Tagged();
   }
-
+  virtual Range* InferRange(Zone* zone);
   virtual void PrintDataTo(StringStream* stream);
 
-  DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList)
-
- private:
-  HObjectAccess store_field_;
-  KnownList known_list_;
-};
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
 
+ protected:
+  virtual bool DataEquals(HValue* other) {
+    HLoadNamedField* b = HLoadNamedField::cast(other);
+    return access_.Equals(b->access_);
+  }
 
-class HLoadNamedField: public HTemplateInstruction<2> {
- public:
+ private:
   HLoadNamedField(HValue* object,
                   HObjectAccess access,
                   HValue* typecheck = NULL)
@@ -5803,37 +5563,6 @@ class HLoadNamedField: public HTemplateInstruction<2> {
     access.SetGVNFlags(this, false);
   }
 
-  HValue* object() { return OperandAt(0); }
-  HValue* typecheck() {
-    ASSERT(HasTypeCheck());
-    return OperandAt(1);
-  }
-
-  bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
-  HObjectAccess access() const { return access_; }
-  Representation field_representation() const {
-      return access_.representation();
-  }
-
-  virtual bool HasEscapingOperandAt(int index) { return false; }
-  virtual Representation RequiredInputRepresentation(int index) {
-    if (index == 0 && access().IsExternalMemory()) {
-      // object must be external in case of external memory access
-      return Representation::External();
-    }
-    return Representation::Tagged();
-  }
-  virtual void PrintDataTo(StringStream* stream);
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
-
- protected:
-  virtual bool DataEquals(HValue* other) {
-    HLoadNamedField* b = HLoadNamedField::cast(other);
-    return access_.Equals(b->access_);
-  }
-
- private:
   virtual bool IsDeletable() const { return true; }
 
   HObjectAccess access_;
@@ -5952,55 +5681,10 @@ enum LoadKeyedHoleMode {
 class HLoadKeyed
     : public HTemplateInstruction<3>, public ArrayInstructionInterface {
  public:
-  HLoadKeyed(HValue* obj,
-             HValue* key,
-             HValue* dependency,
-             ElementsKind elements_kind,
-             LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
-      : bit_field_(0) {
-    bit_field_ = ElementsKindField::encode(elements_kind) |
-        HoleModeField::encode(mode);
-
-    SetOperandAt(0, obj);
-    SetOperandAt(1, key);
-    SetOperandAt(2, dependency != NULL ? dependency : obj);
-
-    if (!is_external()) {
-      // I can detect the case between storing double (holey and fast) and
-      // smi/object by looking at elements_kind_.
-      ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
-             IsFastDoubleElementsKind(elements_kind));
-
-      if (IsFastSmiOrObjectElementsKind(elements_kind)) {
-        if (IsFastSmiElementsKind(elements_kind) &&
-            (!IsHoleyElementsKind(elements_kind) ||
-             mode == NEVER_RETURN_HOLE)) {
-          set_type(HType::Smi());
-          set_representation(Representation::Smi());
-        } else {
-          set_representation(Representation::Tagged());
-        }
-
-        SetGVNFlag(kDependsOnArrayElements);
-      } else {
-        set_representation(Representation::Double());
-        SetGVNFlag(kDependsOnDoubleArrayElements);
-      }
-    } else {
-      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
-          elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-        set_representation(Representation::Double());
-      } else {
-        set_representation(Representation::Integer32());
-      }
-
-      SetGVNFlag(kDependsOnExternalMemory);
-      // Native code could change the specialized array.
-      SetGVNFlag(kDependsOnCalls);
-    }
-
-    SetFlag(kUseGVN);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
+                                 ElementsKind);
+  DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
+                                 ElementsKind, LoadKeyedHoleMode);
 
   bool is_external() const {
     return IsExternalArrayElementsKind(elements_kind());
@@ -6069,6 +5753,56 @@ class HLoadKeyed
   }
 
  private:
+  HLoadKeyed(HValue* obj,
+             HValue* key,
+             HValue* dependency,
+             ElementsKind elements_kind,
+             LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
+      : bit_field_(0) {
+    bit_field_ = ElementsKindField::encode(elements_kind) |
+        HoleModeField::encode(mode);
+
+    SetOperandAt(0, obj);
+    SetOperandAt(1, key);
+    SetOperandAt(2, dependency != NULL ? dependency : obj);
+
+    if (!is_external()) {
+      // I can detect the case between storing double (holey and fast) and
+      // smi/object by looking at elements_kind_.
+      ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
+             IsFastDoubleElementsKind(elements_kind));
+
+      if (IsFastSmiOrObjectElementsKind(elements_kind)) {
+        if (IsFastSmiElementsKind(elements_kind) &&
+            (!IsHoleyElementsKind(elements_kind) ||
+             mode == NEVER_RETURN_HOLE)) {
+          set_type(HType::Smi());
+          set_representation(Representation::Smi());
+        } else {
+          set_representation(Representation::Tagged());
+        }
+
+        SetGVNFlag(kDependsOnArrayElements);
+      } else {
+        set_representation(Representation::Double());
+        SetGVNFlag(kDependsOnDoubleArrayElements);
+      }
+    } else {
+      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+          elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+        set_representation(Representation::Double());
+      } else {
+        set_representation(Representation::Integer32());
+      }
+
+      SetGVNFlag(kDependsOnExternalMemory);
+      // Native code could change the specialized array.
+      SetGVNFlag(kDependsOnCalls);
+    }
+
+    SetFlag(kUseGVN);
+  }
+
   virtual bool IsDeletable() const {
     return !RequiresHoleCheck();
   }
@@ -6132,20 +5866,10 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> {
 };
 
 
-class HStoreNamedField: public HTemplateInstruction<2> {
+class HStoreNamedField: public HTemplateInstruction<3> {
  public:
-  HStoreNamedField(HValue* obj,
-                   HObjectAccess access,
-                   HValue* val)
-      : access_(access),
-        transition_(),
-        transition_unique_id_(),
-        new_space_dominator_(NULL),
-        write_barrier_mode_(UPDATE_WRITE_BARRIER) {
-    SetOperandAt(0, obj);
-    SetOperandAt(1, val);
-    access.SetGVNFlags(this, true);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
+                                 HObjectAccess, HValue*);
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
 
@@ -6174,28 +5898,40 @@ class HStoreNamedField: public HTemplateInstruction<2> {
     return write_barrier_mode_ == SKIP_WRITE_BARRIER;
   }
 
-  HValue* object() { return OperandAt(0); }
-  HValue* value() { return OperandAt(1); }
+  HValue* object() const { return OperandAt(0); }
+  HValue* value() const { return OperandAt(1); }
+  HValue* transition() const { return OperandAt(2); }
 
   HObjectAccess access() const { return access_; }
-  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.
+  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());
     if (map->CanBeDeprecated()) {
       map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
     }
-    transition_ = map;
+    SetOperandAt(2, map_constant);
+    has_transition_ = true;
   }
-  HValue* new_space_dominator() const { return new_space_dominator_; }
 
   bool NeedsWriteBarrier() {
     ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) ||
-           transition_.is_null());
+           !has_transition());
     if (IsSkipWriteBarrier()) return false;
     if (field_representation().IsDouble()) return false;
     if (field_representation().IsSmi()) return false;
     if (field_representation().IsInteger32()) return false;
+    if (field_representation().IsExternal()) return false;
     return StoringValueNeedsWriteBarrier(value()) &&
         ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
   }
@@ -6205,20 +5941,28 @@ class HStoreNamedField: public HTemplateInstruction<2> {
     return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
   }
 
-  virtual void FinalizeUniqueValueId() {
-    transition_unique_id_ = UniqueValueId(transition_);
-  }
-
   Representation field_representation() const {
     return access_.representation();
   }
 
  private:
+  HStoreNamedField(HValue* obj,
+                   HObjectAccess access,
+                   HValue* val)
+      : access_(access),
+        new_space_dominator_(NULL),
+        write_barrier_mode_(UPDATE_WRITE_BARRIER),
+        has_transition_(false) {
+    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_;
+  WriteBarrierMode write_barrier_mode_ : 1;
+  bool has_transition_ : 1;
 };
 
 
@@ -6260,38 +6004,8 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> {
 class HStoreKeyed
     : public HTemplateInstruction<3>, public ArrayInstructionInterface {
  public:
-  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
-              ElementsKind elements_kind)
-      : elements_kind_(elements_kind),
-      index_offset_(0),
-      is_dehoisted_(false),
-      is_uninitialized_(false),
-      new_space_dominator_(NULL) {
-    SetOperandAt(0, obj);
-    SetOperandAt(1, key);
-    SetOperandAt(2, val);
-
-    if (IsFastObjectElementsKind(elements_kind)) {
-      SetFlag(kTrackSideEffectDominators);
-      SetGVNFlag(kDependsOnNewSpacePromotion);
-    }
-    if (is_external()) {
-      SetGVNFlag(kChangesExternalMemory);
-      SetFlag(kAllowUndefinedAsNaN);
-    } else if (IsFastDoubleElementsKind(elements_kind)) {
-      SetGVNFlag(kChangesDoubleArrayElements);
-    } else if (IsFastSmiElementsKind(elements_kind)) {
-      SetGVNFlag(kChangesArrayElements);
-    } else {
-      SetGVNFlag(kChangesArrayElements);
-    }
-
-    // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
-    if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
-        elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
-      SetFlag(kTruncatingToInt32);
-    }
-  }
+  DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
+                                 ElementsKind);
 
   virtual bool HasEscapingOperandAt(int index) { return index != 0; }
   virtual Representation RequiredInputRepresentation(int index) {
@@ -6388,6 +6102,39 @@ class HStoreKeyed
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
 
  private:
+  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
+              ElementsKind elements_kind)
+      : elements_kind_(elements_kind),
+      index_offset_(0),
+      is_dehoisted_(false),
+      is_uninitialized_(false),
+      new_space_dominator_(NULL) {
+    SetOperandAt(0, obj);
+    SetOperandAt(1, key);
+    SetOperandAt(2, val);
+
+    if (IsFastObjectElementsKind(elements_kind)) {
+      SetFlag(kTrackSideEffectDominators);
+      SetGVNFlag(kDependsOnNewSpacePromotion);
+    }
+    if (is_external()) {
+      SetGVNFlag(kChangesExternalMemory);
+      SetFlag(kAllowUndefinedAsNaN);
+    } else if (IsFastDoubleElementsKind(elements_kind)) {
+      SetGVNFlag(kChangesDoubleArrayElements);
+    } else if (IsFastSmiElementsKind(elements_kind)) {
+      SetGVNFlag(kChangesArrayElements);
+    } else {
+      SetGVNFlag(kChangesArrayElements);
+    }
+
+    // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
+    if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
+        elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
+      SetFlag(kTruncatingToInt32);
+    }
+  }
+
   ElementsKind elements_kind_;
   uint32_t index_offset_;
   bool is_dehoisted_ : 1;
@@ -6433,29 +6180,13 @@ class HStoreKeyedGeneric: public HTemplateInstruction<4> {
 
 class HTransitionElementsKind: public HTemplateInstruction<2> {
  public:
-  HTransitionElementsKind(HValue* context,
-                          HValue* object,
-                          Handle<Map> original_map,
-                          Handle<Map> transitioned_map)
-      : original_map_(original_map),
-        transitioned_map_(transitioned_map),
-        original_map_unique_id_(),
-        transitioned_map_unique_id_(),
-        from_kind_(original_map->elements_kind()),
-        to_kind_(transitioned_map->elements_kind()) {
-    SetOperandAt(0, object);
-    SetOperandAt(1, context);
-    SetFlag(kUseGVN);
-    SetGVNFlag(kChangesElementsKind);
-    if (original_map->has_fast_double_elements()) {
-      SetGVNFlag(kChangesElementsPointer);
-      SetGVNFlag(kChangesNewSpacePromotion);
-    }
-    if (transitioned_map->has_fast_double_elements()) {
-      SetGVNFlag(kChangesElementsPointer);
-      SetGVNFlag(kChangesNewSpacePromotion);
-    }
-    set_representation(Representation::Tagged());
+  inline static HTransitionElementsKind* New(Zone* zone,
+                                             HValue* context,
+                                             HValue* object,
+                                             Handle<Map> original_map,
+                                             Handle<Map> transitioned_map) {
+    return new(zone) HTransitionElementsKind(context, object,
+                                             original_map, transitioned_map);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -6486,6 +6217,31 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
   }
 
  private:
+  HTransitionElementsKind(HValue* context,
+                          HValue* object,
+                          Handle<Map> original_map,
+                          Handle<Map> transitioned_map)
+      : original_map_(original_map),
+        transitioned_map_(transitioned_map),
+        original_map_unique_id_(),
+        transitioned_map_unique_id_(),
+        from_kind_(original_map->elements_kind()),
+        to_kind_(transitioned_map->elements_kind()) {
+    SetOperandAt(0, object);
+    SetOperandAt(1, context);
+    SetFlag(kUseGVN);
+    SetGVNFlag(kChangesElementsKind);
+    if (original_map->has_fast_double_elements()) {
+      SetGVNFlag(kChangesElementsPointer);
+      SetGVNFlag(kChangesNewSpacePromotion);
+    }
+    if (transitioned_map->has_fast_double_elements()) {
+      SetGVNFlag(kChangesElementsPointer);
+      SetGVNFlag(kChangesNewSpacePromotion);
+    }
+    set_representation(Representation::Tagged());
+  }
+
   Handle<Map> original_map_;
   Handle<Map> transitioned_map_;
   UniqueValueId original_map_unique_id_;
@@ -6509,10 +6265,6 @@ class HStringAdd: public HBinaryOperation {
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType() {
-    return HType::String();
-  }
-
   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
 
  protected:
@@ -6520,7 +6272,7 @@ class HStringAdd: public HBinaryOperation {
 
  private:
   HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags)
-      : HBinaryOperation(context, left, right), flags_(flags) {
+      : HBinaryOperation(context, left, right, HType::String()), flags_(flags) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnMaps);
@@ -6537,14 +6289,11 @@ class HStringAdd: public HBinaryOperation {
 
 class HStringCharCodeAt: public HTemplateInstruction<3> {
  public:
-  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, string);
-    SetOperandAt(2, index);
-    set_representation(Representation::Integer32());
-    SetFlag(kUseGVN);
-    SetGVNFlag(kDependsOnMaps);
-    SetGVNFlag(kChangesNewSpacePromotion);
+  static HStringCharCodeAt* New(Zone* zone,
+                                HValue* context,
+                                HValue* string,
+                                HValue* index) {
+    return new(zone) HStringCharCodeAt(context, string, index);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -6568,6 +6317,16 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
   }
 
  private:
+  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, string);
+    SetOperandAt(2, index);
+    set_representation(Representation::Integer32());
+    SetFlag(kUseGVN);
+    SetGVNFlag(kDependsOnMaps);
+    SetGVNFlag(kChangesNewSpacePromotion);
+  }
+
   // No side effects: runtime function assumes string + number inputs.
   virtual bool IsDeletable() const { return true; }
 };
@@ -6584,7 +6343,6 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
         ? Representation::Tagged()
         : Representation::Integer32();
   }
-  virtual HType CalculateInferredType() { return HType::String(); }
 
   HValue* context() const { return OperandAt(0); }
   HValue* value() const { return OperandAt(1); }
@@ -6594,7 +6352,8 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
 
  private:
-  HStringCharFromCode(HValue* context, HValue* char_code) {
+  HStringCharFromCode(HValue* context, HValue* char_code)
+      : HTemplateInstruction<2>(HType::String()) {
     SetOperandAt(0, context);
     SetOperandAt(1, char_code);
     set_representation(Representation::Tagged());
@@ -6608,39 +6367,6 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
 };
 
 
-class HStringLength: public HUnaryOperation {
- public:
-  static HInstruction* New(Zone* zone, HValue* string);
-
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Tagged();
-  }
-
-  virtual HType CalculateInferredType() {
-    STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
-    return HType::Smi();
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(StringLength)
-
- protected:
-  virtual bool DataEquals(HValue* other) { return true; }
-
-  virtual Range* InferRange(Zone* zone) {
-    return new(zone) Range(0, String::kMaxLength);
-  }
-
- private:
-  explicit HStringLength(HValue* string) : HUnaryOperation(string) {
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-    SetGVNFlag(kDependsOnMaps);
-  }
-
-  virtual bool IsDeletable() const { return true; }
-};
-
-
 template <int V>
 class HMaterializedLiteral: public HTemplateInstruction<V> {
  public:
@@ -6683,6 +6409,7 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
         flags_(flags) {
     SetOperandAt(0, context);
     SetAllSideEffects();
+    set_type(HType::JSObject());
   }
 
   HValue* context() { return OperandAt(0); }
@@ -6693,7 +6420,6 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
-  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
 
@@ -6709,7 +6435,8 @@ class HFunctionLiteral: public HTemplateInstruction<1> {
   HFunctionLiteral(HValue* context,
                    Handle<SharedFunctionInfo> shared,
                    bool pretenure)
-      : shared_info_(shared),
+      : HTemplateInstruction<1>(HType::JSObject()),
+        shared_info_(shared),
         pretenure_(pretenure),
         has_no_literals_(shared->num_literals() == 0),
         is_generator_(shared->is_generator()),
@@ -6724,7 +6451,6 @@ class HFunctionLiteral: public HTemplateInstruction<1> {
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
-  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
 
@@ -6771,9 +6497,7 @@ class HTypeof: public HTemplateInstruction<2> {
 
 class HTrapAllocationMemento : public HTemplateInstruction<1> {
  public:
-  explicit HTrapAllocationMemento(HValue* obj) {
-    SetOperandAt(0, obj);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -6782,11 +6506,25 @@ class HTrapAllocationMemento : public HTemplateInstruction<1> {
   HValue* object() { return OperandAt(0); }
 
   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
+
+ private:
+  explicit HTrapAllocationMemento(HValue* obj) {
+    SetOperandAt(0, obj);
+  }
 };
 
 
 class HToFastProperties: public HUnaryOperation {
  public:
+  DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
+
+  virtual Representation RequiredInputRepresentation(int index) {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
+
+ private:
   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
     // This instruction is not marked as having side effects, but
     // changes the map of the input operand. Use it only when creating
@@ -6800,13 +6538,6 @@ class HToFastProperties: public HUnaryOperation {
     set_representation(Representation::Tagged());
   }
 
-  virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Tagged();
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
-
- private:
   virtual bool IsDeletable() const { return true; }
 };
 
@@ -6879,15 +6610,7 @@ class HSeqStringSetChar: public HTemplateInstruction<3> {
 
 class HCheckMapValue: public HTemplateInstruction<2> {
  public:
-  HCheckMapValue(HValue* value,
-                 HValue* map) {
-    SetOperandAt(0, value);
-    SetOperandAt(1, map);
-    set_representation(Representation::Tagged());
-    SetFlag(kUseGVN);
-    SetGVNFlag(kDependsOnMaps);
-    SetGVNFlag(kDependsOnElementsKind);
-  }
+  DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -6908,17 +6631,26 @@ class HCheckMapValue: public HTemplateInstruction<2> {
   virtual bool DataEquals(HValue* other) {
     return true;
   }
+
+ private:
+  HCheckMapValue(HValue* value,
+                 HValue* map) {
+    SetOperandAt(0, value);
+    SetOperandAt(1, map);
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+    SetGVNFlag(kDependsOnMaps);
+    SetGVNFlag(kDependsOnElementsKind);
+  }
 };
 
 
 class HForInPrepareMap : public HTemplateInstruction<2> {
  public:
-  HForInPrepareMap(HValue* context,
-                   HValue* object) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, object);
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
+  static HForInPrepareMap* New(Zone* zone,
+                               HValue* context,
+                               HValue* object) {
+    return new(zone) HForInPrepareMap(context, object);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -6935,18 +6667,21 @@ class HForInPrepareMap : public HTemplateInstruction<2> {
   }
 
   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
+
+ private:
+  HForInPrepareMap(HValue* context,
+                   HValue* object) {
+    SetOperandAt(0, context);
+    SetOperandAt(1, object);
+    set_representation(Representation::Tagged());
+    SetAllSideEffects();
+  }
 };
 
 
 class HForInCacheArray : public HTemplateInstruction<2> {
  public:
-  HForInCacheArray(HValue* enumerable,
-                   HValue* keys,
-                   int idx) : idx_(idx) {
-    SetOperandAt(0, enumerable);
-    SetOperandAt(1, keys);
-    set_representation(Representation::Tagged());
-  }
+  DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -6973,6 +6708,14 @@ class HForInCacheArray : public HTemplateInstruction<2> {
   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
 
  private:
+  HForInCacheArray(HValue* enumerable,
+                   HValue* keys,
+                   int idx) : idx_(idx) {
+    SetOperandAt(0, enumerable);
+    SetOperandAt(1, keys);
+    set_representation(Representation::Tagged());
+  }
+
   int idx_;
   HForInCacheArray* index_cache_;
 };
index 67219f5..835a198 100644 (file)
@@ -33,11 +33,7 @@ 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() ||
-      use->IsBitNot()) {
+  if (use->IsBitwise() || use->IsShl() || use->IsSar() || use->IsShr()) {
     return true;
   } else if (use->IsChange() || use->IsSimulate()) {
     // Conversions and deoptimization have special support for unt32.
index 0875f29..837c978 100644 (file)
@@ -609,7 +609,9 @@ void HGraph::Verify(bool do_full_verify) const {
 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
                                int32_t value) {
   if (!pointer->is_set()) {
-    HConstant* constant = new(zone()) HConstant(value);
+    // Can't pass GetInvalidContext() to HConstant::New, because that will
+    // recursively call GetConstant
+    HConstant* constant = HConstant::New(zone(), NULL, value);
     constant->InsertAfter(GetConstantUndefined());
     pointer->set(constant);
   }
@@ -835,9 +837,8 @@ void HGraphBuilder::IfBuilder::Deopt() {
 
 void HGraphBuilder::IfBuilder::Return(HValue* value) {
   HBasicBlock* block = builder_->current_block();
-  HValue* context = builder_->environment()->LookupContext();
   HValue* parameter_count = builder_->graph()->GetConstantMinus1();
-  block->FinishExit(new(zone()) HReturn(value, context, parameter_count));
+  block->FinishExit(builder_->New<HReturn>(value, parameter_count));
   builder_->set_current_block(NULL);
   if (did_else_) {
     first_false_block_ = NULL;
@@ -956,8 +957,9 @@ void HGraphBuilder::LoopBuilder::EndBody() {
 
   // Push the new increment value on the expression stack to merge into the phi.
   builder_->environment()->Push(increment_);
-  builder_->current_block()->GotoNoSimulate(header_block_);
-  header_block_->loop_information()->RegisterBackEdge(body_block_);
+  HBasicBlock* last_block = builder_->current_block();
+  last_block->GotoNoSimulate(header_block_);
+  header_block_->loop_information()->RegisterBackEdge(last_block);
 
   builder_->set_current_block(exit_block_);
   // Pop the phi from the expression stack
@@ -991,15 +993,24 @@ void HGraphBuilder::AddIncrementCounter(StatsCounter* counter,
                                         HValue* context) {
   if (FLAG_native_code_counters && counter->Enabled()) {
     HValue* reference = Add<HConstant>(ExternalReference(counter));
-    HValue* old_value = AddLoad(reference, HObjectAccess::ForCounter(), NULL);
-    HValue* new_value = AddInstruction(
-        HAdd::New(zone(), context, old_value, graph()->GetConstant1()));
+    HValue* old_value = Add<HLoadNamedField>(reference,
+                                             HObjectAccess::ForCounter());
+    HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1());
     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
-    AddStore(reference, HObjectAccess::ForCounter(), new_value);
+    Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
+                          new_value);
   }
 }
 
 
+void HGraphBuilder::AddSimulate(BailoutId id,
+                                RemovableSimulate removable) {
+  ASSERT(current_block() != NULL);
+  ASSERT(no_side_effects_scope_count_ == 0);
+  current_block()->AddSimulate(id, removable);
+}
+
+
 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   HBasicBlock* b = graph()->CreateBasicBlock();
   b->SetInitialEnvironment(env);
@@ -1039,12 +1050,14 @@ 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 undefined and popping extra values so that the
-    // environments match during the join.
+    // 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.
     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()->GetConstantUndefined());
+        from->last_environment()->Push(graph()->GetConstant0());
       } else {
         from->last_environment()->Pop();
       }
@@ -1056,9 +1069,7 @@ void HGraphBuilder::PadEnvironmentForContinuation(
 
 
 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
-  HCheckMaps* check = HCheckMaps::New(obj, map, zone(), top_info());
-  AddInstruction(check);
-  return check;
+  return Add<HCheckMaps>(obj, map, top_info());
 }
 
 
@@ -1090,18 +1101,17 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
                                                 Token::GTE);
   capacity_checker.Then();
 
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
 
   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
-  HValue* max_capacity = AddInstruction(
-      HAdd::New(zone, context, current_capacity, max_gap));
+  HValue* max_capacity = Add<HAdd>(current_capacity, max_gap);
   IfBuilder key_checker(this);
   key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
   key_checker.Then();
   key_checker.ElseDeopt();
   key_checker.End();
 
-  HValue* new_capacity = BuildNewElementsCapacity(context, key);
+  HValue* new_capacity = BuildNewElementsCapacity(key);
   HValue* new_elements = BuildGrowElementsCapacity(object, elements,
                                                    kind, kind, length,
                                                    new_capacity);
@@ -1117,7 +1127,8 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
         HAdd::New(zone, context, key, graph_->GetConstant1()));
     new_length->ClearFlag(HValue::kCanOverflow);
 
-    AddStore(object, HObjectAccess::ForArrayLength(kind), new_length);
+    Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
+                          new_length);
   }
 
   length_checker.Else();
@@ -1174,7 +1185,7 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
     HInstruction* elements = AddLoadElements(object);
 
     HInstruction* empty_fixed_array = Add<HConstant>(
-        isolate()->factory()->empty_fixed_array(), Representation::Tagged());
+        isolate()->factory()->empty_fixed_array());
 
     IfBuilder if_builder(this);
 
@@ -1185,7 +1196,7 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
 
     HInstruction* array_length = is_jsarray
-        ? AddLoad(object, HObjectAccess::ForArrayLength(from_kind), NULL)
+        ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind))
         : elements_length;
 
     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
@@ -1194,7 +1205,7 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
     if_builder.End();
   }
 
-  AddStore(object, HObjectAccess::ForMap(), map);
+  Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
 }
 
 
@@ -1209,7 +1220,6 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
     LoadKeyedHoleMode load_mode,
     KeyedAccessStoreMode store_mode) {
   ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
-  Zone* zone = this->zone();
   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   // on a HElementsTransition instruction. The flag can also be removed if the
   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
@@ -1227,15 +1237,14 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   HValue* elements = AddLoadElements(object, mapcheck);
   if (is_store && (fast_elements || fast_smi_only_elements) &&
       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
-    HCheckMaps* check_cow_map = HCheckMaps::New(
-        elements, isolate()->factory()->fixed_array_map(), zone, top_info());
+    HCheckMaps* check_cow_map = Add<HCheckMaps>(
+        elements, isolate()->factory()->fixed_array_map(), top_info());
     check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
-    AddInstruction(check_cow_map);
   }
   HInstruction* length = NULL;
   if (is_js_array) {
-    length = AddLoad(object, HObjectAccess::ForArrayLength(elements_kind),
-        mapcheck);
+    length = Add<HLoadNamedField>(object,
+        HObjectAccess::ForArrayLength(elements_kind), mapcheck);
   } else {
     length = AddLoadFixedArrayLength(elements);
   }
@@ -1244,8 +1253,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   if (IsExternalArrayElementsKind(elements_kind)) {
     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
       NoObservableSideEffectsScope no_effects(this);
-      HLoadExternalArrayPointer* external_elements =
-          Add<HLoadExternalArrayPointer>(elements);
+       HLoadExternalArrayPointer* external_elements =
+           Add<HLoadExternalArrayPointer>(elements);
       IfBuilder length_checker(this);
       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
       length_checker.Then();
@@ -1295,11 +1304,10 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
         elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
                                             length);
       } else {
-        HCheckMaps* check_cow_map = HCheckMaps::New(
+        HCheckMaps* check_cow_map = Add<HCheckMaps>(
             elements, isolate()->factory()->fixed_array_map(),
-            zone, top_info());
+            top_info());
         check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
-        AddInstruction(check_cow_map);
       }
     }
   }
@@ -1308,37 +1316,29 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
 }
 
 
-HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
-                                             ElementsKind kind,
+HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
                                              HValue* capacity) {
-  Zone* zone = this->zone();
+  int elements_size;
+  InstanceType instance_type;
+
+  if (IsFastDoubleElementsKind(kind)) {
+    elements_size = kDoubleSize;
+    instance_type = FIXED_DOUBLE_ARRAY_TYPE;
+  } else {
+    elements_size = kPointerSize;
+    instance_type = FIXED_ARRAY_TYPE;
+  }
 
-  int elements_size = IsFastDoubleElementsKind(kind)
-      ? kDoubleSize : kPointerSize;
   HConstant* elements_size_value = Add<HConstant>(elements_size);
-  HValue* mul = AddInstruction(
-                    HMul::New(zone, context, capacity, elements_size_value));
+  HValue* mul = Add<HMul>(capacity, elements_size_value);
   mul->ClearFlag(HValue::kCanOverflow);
 
   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
-  HValue* total_size = AddInstruction(
-                           HAdd::New(zone, context, mul, header_size));
+  HValue* total_size = Add<HAdd>(mul, header_size);
   total_size->ClearFlag(HValue::kCanOverflow);
 
-  HAllocate::Flags flags = HAllocate::DefaultFlags(kind);
-  if (isolate()->heap()->ShouldGloballyPretenure()) {
-    // TODO(hpayer): When pretenuring can be internalized, flags can become
-    // private to HAllocate.
-    if (IsFastDoubleElementsKind(kind)) {
-      flags = static_cast<HAllocate::Flags>(
-          flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
-    } else {
-      flags = static_cast<HAllocate::Flags>(
-          flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
-    }
-  }
-
-  return Add<HAllocate>(context, total_size, HType::JSArray(), flags);
+  return Add<HAllocate>(total_size, HType::JSArray(),
+      isolate()->heap()->GetPretenureMode(), instance_type);
 }
 
 
@@ -1351,18 +1351,18 @@ void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
       : factory->fixed_array_map();
 
   AddStoreMapConstant(elements, map);
-  AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity);
+  Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
+                        capacity);
 }
 
 
 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
-    HValue* context,
     ElementsKind kind,
     HValue* capacity) {
   // The HForceRepresentation is to prevent possible deopt on int-smi
   // conversion after allocation but before the new object fields are set.
   capacity = Add<HForceRepresentation>(capacity, Representation::Smi());
-  HValue* new_elements = BuildAllocateElements(context, kind, capacity);
+  HValue* new_elements = BuildAllocateElements(kind, capacity);
   BuildInitializeElementsHeader(new_elements, kind, capacity);
   return new_elements;
 }
@@ -1375,14 +1375,15 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
     HValue* allocation_site_payload,
     HValue* length_field) {
 
-  AddStore(array, HObjectAccess::ForMap(), array_map);
+  Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
 
   HConstant* empty_fixed_array =
-      Add<HConstant>(isolate()->factory()->empty_fixed_array());
+    Add<HConstant>(isolate()->factory()->empty_fixed_array());
 
   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
-  AddStore(array, access, empty_fixed_array);
-  AddStore(array, HObjectAccess::ForArrayLength(elements_kind), length_field);
+  Add<HStoreNamedField>(array, access, empty_fixed_array);
+  Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind),
+                        length_field);
 
   if (mode == TRACK_ALLOCATION_SITE) {
     BuildCreateAllocationMemento(array,
@@ -1395,10 +1396,9 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
     elements_location += AllocationMemento::kSize;
   }
 
-  HInnerAllocatedObject* elements =
-      Add<HInnerAllocatedObject>(array, elements_location);
-  AddStore(array, HObjectAccess::ForElementsPointer(), elements);
-  return elements;
+  HValue* elements = Add<HInnerAllocatedObject>(array, elements_location);
+  Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements);
+  return static_cast<HInnerAllocatedObject*>(elements);
 }
 
 
@@ -1441,8 +1441,10 @@ HInstruction* HGraphBuilder::AddExternalArrayElementAccess(
     return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind);
   } else {
     ASSERT(val == NULL);
-    HLoadKeyed* load = Add<HLoadKeyed>(external_elements, checked_key,
-                                       dependency, elements_kind);
+    HLoadKeyed* load = Add<HLoadKeyed>(external_elements,
+                                       checked_key,
+                                       dependency,
+                                       elements_kind);
     if (FLAG_opt_safe_uint32_operations &&
         elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
       graph()->RecordUint32Instruction(load);
@@ -1484,30 +1486,27 @@ HInstruction* HGraphBuilder::AddFastElementAccess(
 
 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
                                                 HValue* typecheck) {
-  return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck);
+  return Add<HLoadNamedField>(object,
+                              HObjectAccess::ForElementsPointer(),
+                              typecheck);
 }
 
 
 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
-  return AddLoad(object, HObjectAccess::ForFixedArrayLength());
+  return Add<HLoadNamedField>(object,
+                              HObjectAccess::ForFixedArrayLength());
 }
 
 
-HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
-                                                HValue* old_capacity) {
-  Zone* zone = this->zone();
-  HValue* half_old_capacity =
-      AddInstruction(HShr::New(zone, context, old_capacity,
-                               graph_->GetConstant1()));
+HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
+  HValue* half_old_capacity = Add<HShr>(old_capacity, graph_->GetConstant1());
 
-  HValue* new_capacity = AddInstruction(
-      HAdd::New(zone, context, half_old_capacity, old_capacity));
+  HValue* new_capacity = Add<HAdd>(half_old_capacity, old_capacity);
   new_capacity->ClearFlag(HValue::kCanOverflow);
 
   HValue* min_growth = Add<HConstant>(16);
 
-  new_capacity = AddInstruction(
-      HAdd::New(zone, context, new_capacity, min_growth));
+  new_capacity = Add<HAdd>(new_capacity, min_growth);
   new_capacity->ClearFlag(HValue::kCanOverflow);
 
   return new_capacity;
@@ -1531,25 +1530,23 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
                                                  ElementsKind new_kind,
                                                  HValue* length,
                                                  HValue* new_capacity) {
-  HValue* context = environment()->LookupContext();
-
   BuildNewSpaceArrayCheck(new_capacity, new_kind);
 
   HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
-      context, new_kind, new_capacity);
+      new_kind, new_capacity);
 
-  BuildCopyElements(context, elements, kind,
+  BuildCopyElements(elements, kind,
                     new_elements, new_kind,
                     length, new_capacity);
 
-  AddStore(object, HObjectAccess::ForElementsPointer(), new_elements);
+  Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
+                        new_elements);
 
   return new_elements;
 }
 
 
-void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
-                                              HValue* elements,
+void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
                                               ElementsKind elements_kind,
                                               HValue* from,
                                               HValue* to) {
@@ -1591,7 +1588,7 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
       Add<HStoreKeyed>(elements, key, hole, elements_kind);
     }
   } else {
-    LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
+    LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
 
     HValue* key = builder.BeginBody(from, to, Token::LT);
 
@@ -1602,8 +1599,7 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
 }
 
 
-void HGraphBuilder::BuildCopyElements(HValue* context,
-                                      HValue* from_elements,
+void HGraphBuilder::BuildCopyElements(HValue* from_elements,
                                       ElementsKind from_elements_kind,
                                       HValue* to_elements,
                                       ElementsKind to_elements_kind,
@@ -1617,11 +1613,11 @@ void HGraphBuilder::BuildCopyElements(HValue* context,
     // If the copy might trigger a GC, make sure that the FixedArray is
     // pre-initialized with holes to make sure that it's always in a consistent
     // state.
-    BuildFillElementsWithHole(context, to_elements, to_elements_kind,
+    BuildFillElementsWithHole(to_elements, to_elements_kind,
                               graph()->GetConstant0(), capacity);
   }
 
-  LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
+  LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
 
   HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
 
@@ -1643,14 +1639,13 @@ void HGraphBuilder::BuildCopyElements(HValue* context,
 
   if (!pre_fill_with_holes && length != capacity) {
     // Fill unused capacity with the hole.
-    BuildFillElementsWithHole(context, to_elements, to_elements_kind,
+    BuildFillElementsWithHole(to_elements, to_elements_kind,
                               key, capacity);
   }
 }
 
 
-HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
-                                              HValue* boilerplate,
+HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
                                               HValue* allocation_site,
                                               AllocationSiteMode mode,
                                               ElementsKind kind,
@@ -1663,26 +1658,28 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
     size += AllocationMemento::kSize;
   }
   int elems_offset = size;
+  InstanceType instance_type = IsFastDoubleElementsKind(kind) ?
+      FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
   if (length > 0) {
     size += IsFastDoubleElementsKind(kind)
         ? FixedDoubleArray::SizeFor(length)
         : FixedArray::SizeFor(length);
   }
 
-  HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind);
   // Allocate both the JS array and the elements array in one big
   // allocation. This avoids multiple limit checks.
   HValue* size_in_bytes = Add<HConstant>(size);
-  HInstruction* object = Add<HAllocate>(context,
-                                        size_in_bytes,
+  HInstruction* object = Add<HAllocate>(size_in_bytes,
                                         HType::JSObject(),
-                                        allocate_flags);
+                                        NOT_TENURED,
+                                        instance_type);
 
   // Copy the JS array part.
   for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
     if ((i != JSArray::kElementsOffset) || (length == 0)) {
       HObjectAccess access = HObjectAccess::ForJSArrayOffset(i);
-      AddStore(object, access, AddLoad(boilerplate, access));
+      Add<HStoreNamedField>(object, access,
+                            Add<HLoadNamedField>(boilerplate, access));
     }
   }
 
@@ -1696,12 +1693,14 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
     // elements pointer in the resulting object.
     HValue* boilerplate_elements = AddLoadElements(boilerplate);
     HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
-    AddStore(object, HObjectAccess::ForElementsPointer(), object_elements);
+    Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
+                          object_elements);
 
     // Copy the elements array header.
     for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
       HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
-      AddStore(object_elements, access, AddLoad(boilerplate_elements, access));
+      Add<HStoreNamedField>(object_elements, access,
+                            Add<HLoadNamedField>(boilerplate_elements, access));
     }
 
     // Copy the elements array contents.
@@ -1720,39 +1719,6 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
 }
 
 
-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 =
-            HMul::New(zone(), environment()->LookupContext(),
-                      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(zone()) HBitNot(input);
-  }
-}
-
-
 void HGraphBuilder::BuildCompareNil(
     HValue* value,
     Handle<Type> type,
@@ -1803,22 +1769,22 @@ HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object,
       isolate()->heap()->allocation_memento_map());
   AddStoreMapConstant(alloc_memento, alloc_memento_map);
   HObjectAccess access = HObjectAccess::ForAllocationMementoSite();
-  AddStore(alloc_memento, access, alloc_site);
+  Add<HStoreNamedField>(alloc_memento, access, alloc_site);
   return alloc_memento;
 }
 
 
-HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) {
+HInstruction* HGraphBuilder::BuildGetNativeContext() {
   // Get the global context, then the native context
-  HInstruction* global_object = Add<HGlobalObject>(context);
+  HInstruction* global_object = Add<HGlobalObject>();
   HObjectAccess access = HObjectAccess::ForJSObjectOffset(
       GlobalObject::kNativeContextOffset);
-  return AddLoad(global_object, access);
+  return Add<HLoadNamedField>(global_object, access);
 }
 
 
-HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) {
-  HInstruction* native_context = BuildGetNativeContext(context);
+HInstruction* HGraphBuilder::BuildGetArrayFunction() {
+  HInstruction* native_context = BuildGetNativeContext();
   HInstruction* index =
       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
   return Add<HLoadKeyed>(
@@ -1852,7 +1818,7 @@ HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
 }
 
 
-HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) {
+HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
   if (kind_ == GetInitialFastElementsKind()) {
     // No need for a context lookup if the kind_ matches the initial
     // map, because we can just load the map in that case.
@@ -1861,7 +1827,7 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) {
         builder()->BuildLoadNamedField(constructor_function_, access));
   }
 
-  HInstruction* native_context = builder()->BuildGetNativeContext(context);
+  HInstruction* native_context = builder()->BuildGetNativeContext();
   HInstruction* index = builder()->Add<HConstant>(
       static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
 
@@ -1885,7 +1851,6 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
 
 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
     HValue* length_node) {
-  HValue* context = builder()->environment()->LookupContext();
   ASSERT(length_node != NULL);
 
   int base_size = JSArray::kSize;
@@ -1898,15 +1863,12 @@ HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
 
   HInstruction* elements_size_value =
       builder()->Add<HConstant>(elements_size());
-  HInstruction* mul = HMul::New(zone(), context, length_node,
-                                elements_size_value);
+  HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value);
   mul->ClearFlag(HValue::kCanOverflow);
-  builder()->AddInstruction(mul);
 
   HInstruction* base = builder()->Add<HConstant>(base_size);
-  HInstruction* total_size = HAdd::New(zone(), context, base, mul);
+  HInstruction* total_size = builder()->Add<HAdd>(base, mul);
   total_size->ClearFlag(HValue::kCanOverflow);
-  builder()->AddInstruction(total_size);
   return total_size;
 }
 
@@ -1947,8 +1909,6 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
                                                      HValue* capacity,
                                                      HValue* length_field,
                                                      bool fill_with_hole) {
-  HValue* context = builder()->environment()->LookupContext();
-
   // These HForceRepresentations are because we store these as fields in the
   // objects we construct, and an int32-to-smi HChange could deopt. Accept
   // the deopt possibility now, before allocation occurs.
@@ -1956,18 +1916,16 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
                                                   Representation::Smi());
   length_field = builder()->Add<HForceRepresentation>(length_field,
                                                       Representation::Smi());
-
   // Allocate (dealing with failure appropriately)
-  HAllocate::Flags flags = HAllocate::DefaultFlags(kind_);
-  HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes,
-                                                    HType::JSArray(), flags);
+  HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes,
+      HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
 
   // Fill in the fields: map, properties, length
   HValue* map;
   if (allocation_site_payload_ == NULL) {
     map = EmitInternalMapCode();
   } else {
-    map = EmitMapCode(context);
+    map = EmitMapCode();
   }
   elements_location_ = builder()->BuildJSArrayHeader(new_object,
                                                      map,
@@ -1980,7 +1938,7 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
 
   if (fill_with_hole) {
-    builder()->BuildFillElementsWithHole(context, elements_location_, kind_,
+    builder()->BuildFillElementsWithHole(elements_location_, kind_,
                                          graph()->GetConstant0(), capacity);
   }
 
@@ -1988,20 +1946,6 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
 }
 
 
-HStoreNamedField* HGraphBuilder::AddStore(HValue *object,
-                                          HObjectAccess access,
-                                          HValue *val) {
-  return Add<HStoreNamedField>(object, access, val);
-}
-
-
-HLoadNamedField* HGraphBuilder::AddLoad(HValue *object,
-                                        HObjectAccess access,
-                                        HValue *typecheck) {
-  return Add<HLoadNamedField>(object, access, typecheck);
-}
-
-
 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
                                                      Handle<Map> map) {
   return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
@@ -2009,15 +1953,14 @@ HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
 }
 
 
-HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin,
-                                        HValue* context) {
-  HGlobalObject* global_object = Add<HGlobalObject>(context);
+HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
+  HGlobalObject* global_object = Add<HGlobalObject>();
   HObjectAccess access = HObjectAccess::ForJSObjectOffset(
       GlobalObject::kBuiltinsOffset);
-  HValue* builtins = AddLoad(global_object, access);
+  HValue* builtins = Add<HLoadNamedField>(global_object, access);
   HObjectAccess function_access = HObjectAccess::ForJSObjectOffset(
       JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
-  return AddLoad(builtins, function_access);
+  return Add<HLoadNamedField>(builtins, function_access);
 }
 
 
@@ -2606,7 +2549,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("bad value context for arguments value");
+    owner()->Bailout(kBadValueContextForArgumentsValue);
   }
   owner()->Push(value);
 }
@@ -2658,7 +2601,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("bad value context for arguments object value");
+    return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   }
   owner()->AddInstruction(instr);
   owner()->Push(instr);
@@ -2671,7 +2614,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("bad value context for arguments object value");
+    return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   }
   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
@@ -2761,7 +2704,7 @@ void TestContext::BuildBranch(HValue* value) {
   // branch.
   HOptimizedGraphBuilder* builder = owner();
   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
-    builder->Bailout("arguments object value in a test context");
+    builder->Bailout(kArgumentsObjectValueInATestContext);
   }
   if (value->IsConstant()) {
     HConstant* constant_value = HConstant::cast(value);
@@ -2807,7 +2750,7 @@ void TestContext::BuildBranch(HValue* value) {
   } while (false)
 
 
-void HOptimizedGraphBuilder::Bailout(const char* reason) {
+void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
   current_info()->set_bailout_reason(reason);
   SetStackOverflow();
 }
@@ -2866,16 +2809,16 @@ void HOptimizedGraphBuilder::VisitExpressions(
 
 bool HOptimizedGraphBuilder::BuildGraph() {
   if (current_info()->function()->is_generator()) {
-    Bailout("function is a generator");
+    Bailout(kFunctionIsAGenerator);
     return false;
   }
   Scope* scope = current_info()->scope();
   if (scope->HasIllegalRedeclaration()) {
-    Bailout("function with illegal redeclaration");
+    Bailout(kFunctionWithIllegalRedeclaration);
     return false;
   }
   if (scope->calls_eval()) {
-    Bailout("function calls eval");
+    Bailout(kFunctionCallsEval);
     return false;
   }
   SetUpScope(scope);
@@ -2909,7 +2852,7 @@ bool HOptimizedGraphBuilder::BuildGraph() {
   VisitDeclarations(scope->declarations());
   Add<HSimulate>(BailoutId::Declarations());
 
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   Add<HStackCheck>(context, HStackCheck::kFunctionEntry);
 
   VisitStatements(current_info()->function()->body());
@@ -2941,8 +2884,7 @@ bool HOptimizedGraphBuilder::BuildGraph() {
 }
 
 
-bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
-  *bailout_reason = SmartArrayPointer<char>();
+bool HGraph::Optimize(BailoutReason* bailout_reason) {
   OrderBlocks();
   AssignDominators();
 
@@ -2963,14 +2905,12 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
 
   Run<HPropagateDeoptimizingMarkPhase>();
   if (!CheckConstPhiUses()) {
-    *bailout_reason = SmartArrayPointer<char>(StrDup(
-        "Unsupported phi use of const variable"));
+    *bailout_reason = kUnsupportedPhiUseOfConstVariable;
     return false;
   }
   Run<HRedundantPhiEliminationPhase>();
   if (!CheckArgumentsPhiUses()) {
-    *bailout_reason = SmartArrayPointer<char>(StrDup(
-        "Unsupported phi use of arguments"));
+    *bailout_reason = kUnsupportedPhiUseOfArguments;
     return false;
   }
 
@@ -3010,11 +2950,10 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
   // Eliminate redundant stack checks on backwards branches.
   Run<HStackCheckEliminationPhase>();
 
-  if (FLAG_idefs) SetupInformativeDefinitions();
-  if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
+  if (FLAG_array_bounds_checks_elimination) {
     Run<HBoundsCheckEliminationPhase>();
   }
-  if (FLAG_array_bounds_checks_hoisting && !FLAG_idefs) {
+  if (FLAG_array_bounds_checks_hoisting) {
     Run<HBoundsCheckHoistingPhase>();
   }
   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
@@ -3026,50 +2965,6 @@ bool HGraph::Optimize(SmartArrayPointer<char>* 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);
 
@@ -3120,15 +3015,19 @@ HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
 
 
 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
-  HConstant* undefined_constant = Add<HConstant>(
-      isolate()->factory()->undefined_value());
+  // First special is HContext.
+  HInstruction* context = Add<HContext>();
+  environment()->BindContext(context);
+
+  HConstant* undefined_constant = HConstant::cast(Add<HConstant>(
+      isolate()->factory()->undefined_value()));
   graph()->set_undefined_constant(undefined_constant);
 
   // Create an arguments object containing the initial parameters.  Set the
   // initial values of parameters including "this" having parameter index 0.
   ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
   HArgumentsObject* arguments_object =
-      new(zone()) HArgumentsObject(environment()->parameter_count(), zone());
+      New<HArgumentsObject>(environment()->parameter_count());
   for (int i = 0; i < environment()->parameter_count(); ++i) {
     HInstruction* parameter = Add<HParameter>(i);
     arguments_object->AddArgument(parameter, zone());
@@ -3137,10 +3036,6 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
   AddInstruction(arguments_object);
   graph()->SetArgumentsObject(arguments_object);
 
-  // First special is HContext.
-  HInstruction* context = Add<HContext>();
-  environment()->BindContext(context);
-
   // Initialize specials and locals to undefined.
   for (int i = environment()->parameter_count() + 1;
        i < environment()->length();
@@ -3152,7 +3047,7 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
   // not have declarations).
   if (scope->arguments() != NULL) {
     if (!scope->arguments()->IsStackAllocated()) {
-      return Bailout("context-allocated arguments");
+      return Bailout(kContextAllocatedArguments);
     }
 
     environment()->Bind(scope->arguments(),
@@ -3173,7 +3068,7 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   if (stmt->scope() != NULL) {
-    return Bailout("ScopedBlock");
+    return Bailout(kScopedBlock);
   }
   BreakAndContinueInfo break_info(stmt);
   { BreakAndContinueScope push(&break_info, this);
@@ -3385,7 +3280,7 @@ void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("WithStatement");
+  return Bailout(kWithStatement);
 }
 
 
@@ -3400,15 +3295,15 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   ZoneList<CaseClause*>* clauses = stmt->cases();
   int clause_count = clauses->length();
   if (clause_count > kCaseClauseLimit) {
-    return Bailout("SwitchStatement: too many clauses");
+    return Bailout(kSwitchStatementTooManyClauses);
   }
 
   ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
   if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) {
-    return Bailout("SwitchStatement: mixed or non-literal switch labels");
+    return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels);
   }
 
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
 
   CHECK_ALIVE(VisitForValue(stmt->tag()));
   Add<HSimulate>(stmt->EntryId());
@@ -3556,9 +3451,9 @@ void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
                                            BreakAndContinueInfo* break_info) {
   BreakAndContinueScope push(break_info, this);
   Add<HSimulate>(stmt->StackCheckId());
-  HValue* context = environment()->LookupContext();
-  HStackCheck* stack_check = Add<HStackCheck>(
-      context, HStackCheck::kBackwardsBranch);
+  HValue* context = environment()->context();
+  HStackCheck* stack_check = HStackCheck::cast(Add<HStackCheck>(
+      context, HStackCheck::kBackwardsBranch));
   ASSERT(loop_entry->IsLoopHeader());
   loop_entry->loop_information()->set_stack_check(stack_check);
   CHECK_BAILOUT(Visit(stmt->body()));
@@ -3697,16 +3592,16 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   ASSERT(current_block()->HasPredecessor());
 
   if (!FLAG_optimize_for_in) {
-    return Bailout("ForInStatement optimization is disabled");
+    return Bailout(kForInStatementOptimizationIsDisabled);
   }
 
   if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
-    return Bailout("ForInStatement is not fast case");
+    return Bailout(kForInStatementIsNotFastCase);
   }
 
   if (!stmt->each()->IsVariableProxy() ||
       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
-    return Bailout("ForInStatement with non-local each variable");
+    return Bailout(kForInStatementWithNonLocalEachVariable);
   }
 
   Variable* each_var = stmt->each()->AsVariableProxy()->var();
@@ -3714,8 +3609,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
   HValue* enumerable = Top();  // Leave enumerable at the top.
 
-  HInstruction* map = Add<HForInPrepareMap>(
-      environment()->LookupContext(), enumerable);
+  HInstruction* map = Add<HForInPrepareMap>(enumerable);
   Add<HSimulate>(stmt->PrepareId());
 
   HInstruction* array = Add<HForInCacheArray>(
@@ -3781,9 +3675,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
     set_current_block(body_exit);
 
     HValue* current_index = Pop();
-    HInstruction* new_index = HAdd::New(zone(),
-                                        environment()->LookupContext(),
-                                        current_index,
+    HInstruction* new_index = New<HAdd>(current_index,
                                         graph()->GetConstant1());
     PushAndAdd(new_index);
     body_exit = current_block();
@@ -3803,7 +3695,7 @@ void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("ForOfStatement");
+  return Bailout(kForOfStatement);
 }
 
 
@@ -3811,7 +3703,7 @@ void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("TryCatchStatement");
+  return Bailout(kTryCatchStatement);
 }
 
 
@@ -3820,7 +3712,7 @@ void HOptimizedGraphBuilder::VisitTryFinallyStatement(
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("TryFinallyStatement");
+  return Bailout(kTryFinallyStatement);
 }
 
 
@@ -3828,7 +3720,7 @@ void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("DebuggerStatement");
+  return Bailout(kDebuggerStatement);
 }
 
 
@@ -3862,7 +3754,7 @@ void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   }
   // We also have a stack overflow if the recursive compilation did.
   if (HasStackOverflow()) return;
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HFunctionLiteral* instr =
       new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
   return ast_context()->ReturnInstruction(instr, expr->id());
@@ -3874,7 +3766,7 @@ void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral(
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("SharedFunctionInfoLiteral");
+  return Bailout(kSharedFunctionInfoLiteral);
 }
 
 
@@ -3936,7 +3828,7 @@ HOptimizedGraphBuilder::GlobalPropertyAccess
 
 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
   ASSERT(var->IsContextSlot());
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   int length = current_info()->scope()->ContextChainLength(var->scope());
   while (length-- > 0) {
     context = Add<HOuterContext>(context);
@@ -3954,14 +3846,14 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
     case Variable::UNALLOCATED: {
       if (IsLexicalVariableMode(variable->mode())) {
         // TODO(rossberg): should this be an ASSERT?
-        return Bailout("reference to global lexical variable");
+        return Bailout(kReferenceToGlobalLexicalVariable);
       }
       // Handle known global constants like 'undefined' specially to avoid a
       // load from a global cell for them.
       Handle<Object> constant_value =
           isolate()->factory()->GlobalConstantFor(variable->name());
       if (!constant_value.is_null()) {
-        HConstant* instr = new(zone()) HConstant(constant_value);
+        HConstant* instr = New<HConstant>(constant_value);
         return ast_context()->ReturnInstruction(instr, expr->id());
       }
 
@@ -3984,7 +3876,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
             constant_object =
                 FlattenGetString(Handle<String>::cast(constant_object));
           }
-          HConstant* constant = new(zone()) HConstant(constant_object);
+          HConstant* constant = New<HConstant>(constant_object);
           return ast_context()->ReturnInstruction(constant, expr->id());
         } else {
           HLoadGlobalCell* instr =
@@ -3992,7 +3884,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
           return ast_context()->ReturnInstruction(instr, expr->id());
         }
       } else {
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HGlobalObject* global_object = new(zone()) HGlobalObject(context);
         AddInstruction(global_object);
         HLoadGlobalGeneric* instr =
@@ -4011,7 +3903,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
       if (value == graph()->GetConstantHole()) {
         ASSERT(IsDeclaredVariableMode(variable->mode()) &&
                variable->mode() != VAR);
-        return Bailout("reference to uninitialized variable");
+        return Bailout(kReferenceToUninitializedVariable);
       }
       return ast_context()->ReturnValue(value);
     }
@@ -4023,7 +3915,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
     }
 
     case Variable::LOOKUP:
-      return Bailout("reference to a variable which requires dynamic lookup");
+      return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
   }
 }
 
@@ -4032,7 +3924,7 @@ void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  HConstant* instr = new(zone()) HConstant(expr->value());
+  HConstant* instr = New<HConstant>(expr->value());
   return ast_context()->ReturnInstruction(instr, expr->id());
 }
 
@@ -4043,7 +3935,7 @@ void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   ASSERT(current_block()->HasPredecessor());
   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   Handle<FixedArray> literals(closure->literals());
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
 
   HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
                                                      literals,
@@ -4144,8 +4036,7 @@ 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;
   }
 
@@ -4220,7 +4111,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HInstruction* literal;
 
   // Check whether to use fast or slow deep-copying for boilerplate.
@@ -4265,8 +4156,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
     Runtime::FunctionId function_id =
         (expr->depth() > 1 || expr->may_store_doubles())
         ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow;
-    literal = Add<HCallRuntime>(context,
-                                isolate()->factory()->empty_string(),
+    literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
                                 Runtime::FunctionForId(function_id),
                                 4);
   }
@@ -4323,7 +4213,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
       case ObjectLiteral::Property::PROTOTYPE:
       case ObjectLiteral::Property::SETTER:
       case ObjectLiteral::Property::GETTER:
-        return Bailout("Object literal with complex property");
+        return Bailout(kObjectLiteralWithComplexProperty);
       default: UNREACHABLE();
     }
   }
@@ -4348,7 +4238,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   ASSERT(current_block()->HasPredecessor());
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HInstruction* literal;
 
   Handle<AllocationSite> site;
@@ -4362,7 +4252,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
     raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
         isolate(), literals, expr->constant_elements());
     if (raw_boilerplate.is_null()) {
-      return Bailout("array boilerplate creation failed");
+      return Bailout(kArrayBoilerplateCreationFailed);
     }
 
     site = isolate()->factory()->NewAllocationSite();
@@ -4427,15 +4317,14 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
 
     Runtime::FunctionId function_id = (expr->depth() > 1)
         ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
-    literal = Add<HCallRuntime>(context,
-                                isolate()->factory()->empty_string(),
+    literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
                                 Runtime::FunctionForId(function_id),
                                 3);
 
     // De-opt if elements kind changed from boilerplate_elements_kind.
     Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
                                   isolate());
-    AddInstruction(HCheckMaps::New(literal, map, zone(), top_info()));
+    Add<HCheckMaps>(literal, map, top_info());
   }
 
   // The array is expected in the bailout environment during computation
@@ -4454,7 +4343,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
 
     CHECK_ALIVE(VisitForValue(subexpr));
     HValue* value = Pop();
-    if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
+    if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
 
     elements = AddLoadElements(literal);
 
@@ -4512,15 +4401,7 @@ static bool ComputeLoadStoreField(Handle<Map> type,
 
 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) {
   BuildCheckHeapObject(object);
-  AddInstruction(HCheckMaps::New(object, map, zone(), top_info()));
-}
-
-
-void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object,
-                                                         Handle<Map> map) {
-  BuildCheckHeapObject(object);
-  AddInstruction(HCheckMaps::NewWithTransitions(
-      object, map, zone(), top_info()));
+  Add<HCheckMaps>(object, map, top_info());
 }
 
 
@@ -4542,7 +4423,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("improper object on prototype chain for store");
+        Bailout(kImproperObjectOnPrototypeChainForStore);
         return NULL;
       }
       // We only need to check up to the preexisting property.
@@ -4555,9 +4436,9 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
       ASSERT(proto->GetPrototype(isolate())->IsNull());
     }
     ASSERT(proto->IsJSObject());
-    Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())),
-                             Handle<JSObject>(JSObject::cast(proto)),
-                             zone(), top_info());
+    BuildCheckPrototypeMaps(
+        Handle<JSObject>(JSObject::cast(map->prototype())),
+        Handle<JSObject>(JSObject::cast(proto)));
   }
 
   HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
@@ -4571,28 +4452,32 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
       // The store requires a mutable HeapNumber to be allocated.
       NoObservableSideEffectsScope no_side_effects(this);
       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
-      HInstruction* heap_number = Add<HAllocate>(
-          environment()->LookupContext(), heap_number_size,
-          HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE);
+      HInstruction* heap_number = Add<HAllocate>(heap_number_size,
+          HType::HeapNumber(), isolate()->heap()->GetPretenureMode(),
+          HEAP_NUMBER_TYPE);
       AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map());
-      AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value);
-      instr = new(zone()) HStoreNamedField(
-          object, heap_number_access, heap_number);
+      Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
+                            value);
+      instr = New<HStoreNamedField>(object, heap_number_access,
+                                           heap_number);
     } else {
       // Already holds a HeapNumber; load the box and write its value field.
-      HInstruction* heap_number = AddLoad(object, heap_number_access);
+      HInstruction* heap_number = Add<HLoadNamedField>(object,
+                                                       heap_number_access);
       heap_number->set_type(HType::HeapNumber());
-      instr = new(zone()) HStoreNamedField(heap_number,
-          HObjectAccess::ForHeapNumberValue(), value);
+      instr = New<HStoreNamedField>(heap_number,
+                                    HObjectAccess::ForHeapNumberValue(),
+                                    value);
     }
   } else {
     // This is a normal store.
-    instr = new(zone()) HStoreNamedField(object, field_access, value);
+    instr = New<HStoreNamedField>(object, field_access, value);
   }
 
   if (transition_to_field) {
     Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
-    instr->SetTransition(transition, top_info());
+    HConstant* transition_constant = Add<HConstant>(transition);
+    instr->SetTransition(transition_constant, 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);
@@ -4605,7 +4490,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
     HValue* object,
     Handle<String> name,
     HValue* value) {
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   return new(zone()) HStoreNamedGeneric(
                          context,
                          object,
@@ -4623,7 +4508,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
   // Handle a store to a known field.
   LookupResult lookup(isolate());
   if (ComputeLoadStoreField(map, name, &lookup, true)) {
-    AddCheckMapsWithTransitions(object, map);
+    AddCheckMap(object, map);
     return BuildStoreNamedField(object, name, value, map, &lookup);
   }
 
@@ -4682,7 +4567,7 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
   if (count == types->length()) {
     // Everything matched; can use monomorphic load.
     BuildCheckHeapObject(object);
-    AddInstruction(HCheckMaps::New(object, types, zone()));
+    Add<HCheckMaps>(object, types);
     return BuildLoadNamedField(object, access);
   }
 
@@ -4704,13 +4589,12 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
   if (!lookup.IsField()) return NULL;
 
   BuildCheckHeapObject(object);
-  AddInstruction(HCheckMaps::New(object, types, zone()));
+  Add<HCheckMaps>(object, types);
 
   Handle<JSObject> holder(lookup.holder());
   Handle<Map> holder_map(holder->map());
-  AddInstruction(new(zone()) HCheckPrototypeMaps(
-      Handle<JSObject>::cast(prototype), holder, zone(), top_info()));
-  HValue* holder_value = AddInstruction(new(zone()) HConstant(holder));
+  BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
+  HValue* holder_value = Add<HConstant>(holder);
   return BuildLoadNamedField(holder_value,
       HObjectAccess::ForField(holder_map, &lookup, name));
 }
@@ -4726,7 +4610,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
   if (instr == NULL) {
     // Something did not match; must use a polymorphic load.
     BuildCheckHeapObject(object);
-    HValue* context = environment()->LookupContext();
+    HValue* context = environment()->context();
     instr = new(zone()) HLoadNamedFieldPolymorphic(
         context, object, types, name, zone());
   }
@@ -4783,7 +4667,7 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
 
   // Everything matched; can use monomorphic store.
   BuildCheckHeapObject(object);
-  AddInstruction(HCheckMaps::New(object, types, zone()));
+  Add<HCheckMaps>(object, types);
   HInstruction* store;
   CHECK_ALIVE_OR_RETURN(
       store = BuildStoreNamedField(
@@ -4955,10 +4839,9 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
     }
   } else {
-    HValue* context =  environment()->LookupContext();
-    HGlobalObject* global_object = Add<HGlobalObject>(context);
+    HGlobalObject* global_object = Add<HGlobalObject>();
     HStoreGlobalGeneric* instr =
-        Add<HStoreGlobalGeneric>(context, global_object, var->name(),
+        Add<HStoreGlobalGeneric>(global_object, var->name(),
                                  value, function_strict_mode_flag());
     instr->set_position(position);
     ASSERT(instr->HasObservableSideEffects());
@@ -5044,7 +4927,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
   if (proxy != NULL) {
     Variable* var = proxy->var();
     if (var->mode() == LET)  {
-      return Bailout("unsupported let compound assignment");
+      return Bailout(kUnsupportedLetCompoundAssignment);
     }
 
     CHECK_ALIVE(VisitForValue(operation));
@@ -5060,7 +4943,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
       case Variable::PARAMETER:
       case Variable::LOCAL:
         if (var->mode() == CONST)  {
-          return Bailout("unsupported const compound assignment");
+          return Bailout(kUnsupportedConstCompoundAssignment);
         }
         BindIfLive(var, Top());
         break;
@@ -5076,8 +4959,7 @@ 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(
-                  "assignment to parameter, function uses arguments object");
+              Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
             }
           }
         }
@@ -5099,8 +4981,8 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
         }
 
         HValue* context = BuildContextChainWalk(var);
-        HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
-                                                          mode, Top());
+        HStoreContextSlot* instr = Add<HStoreContextSlot>(
+            context, var->index(), mode, Top());
         if (instr->HasObservableSideEffects()) {
           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
@@ -5108,7 +4990,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
       }
 
       case Variable::LOOKUP:
-        return Bailout("compound assignment to lookup slot");
+        return Bailout(kCompoundAssignmentToLookupSlot);
     }
     return ast_context()->ReturnValue(Pop());
 
@@ -5197,7 +5079,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
     }
 
   } else {
-    return Bailout("invalid lhs in compound assignment");
+    return Bailout(kInvalidLhsInCompoundAssignment);
   }
 }
 
@@ -5234,11 +5116,11 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
       }
     } else if (var->mode() == CONST_HARMONY) {
       if (expr->op() != Token::INIT_CONST_HARMONY) {
-        return Bailout("non-initializer assignment to const");
+        return Bailout(kNonInitializerAssignmentToConst);
       }
     }
 
-    if (proxy->IsArguments()) return Bailout("assignment to arguments");
+    if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
 
     // Handle the assignment.
     switch (var->location()) {
@@ -5257,7 +5139,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("assignment to let variable before initialization");
+            return Bailout(kAssignmentToLetVariableBeforeInitialization);
           }
         }
         // We do not allow the arguments object to occur in a context where it
@@ -5279,7 +5161,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("assignment to parameter in arguments object");
+              return Bailout(kAssignmentToParameterInArgumentsObject);
             }
           }
         }
@@ -5311,8 +5193,8 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
         }
 
         HValue* context = BuildContextChainWalk(var);
-        HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
-                                                          mode, Top());
+        HStoreContextSlot* instr = Add<HStoreContextSlot>(
+            context, var->index(), mode, Top());
         if (instr->HasObservableSideEffects()) {
           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
         }
@@ -5320,10 +5202,10 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
       }
 
       case Variable::LOOKUP:
-        return Bailout("assignment to LOOKUP variable");
+        return Bailout(kAssignmentToLOOKUPVariable);
     }
   } else {
-    return Bailout("invalid left-hand side in assignment");
+    return Bailout(kInvalidLeftHandSideInAssignment);
   }
 }
 
@@ -5344,9 +5226,8 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
   ASSERT(ast_context()->IsEffect());
   CHECK_ALIVE(VisitForValue(expr->exception()));
 
-  HValue* context = environment()->LookupContext();
   HValue* value = environment()->Pop();
-  HThrow* instr = Add<HThrow>(context, value);
+  HThrow* instr = Add<HThrow>(value);
   instr->set_position(expr->position());
   Add<HSimulate>(expr->id());
   current_block()->FinishExit(new(zone()) HAbnormalExit);
@@ -5355,17 +5236,32 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
 
 
 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
-    HObjectAccess access) {
+                                                    HObjectAccess access,
+                                                    HValue* typecheck) {
   if (FLAG_track_double_fields && access.representation().IsDouble()) {
     // load the heap number
-    HLoadNamedField* heap_number =
-        AddLoad(object, access.WithRepresentation(Representation::Tagged()));
+    HLoadNamedField* heap_number = Add<HLoadNamedField>(
+        object, access.WithRepresentation(Representation::Tagged()));
     heap_number->set_type(HType::HeapNumber());
     // load the double value from it
-    return new(zone()) HLoadNamedField(heap_number,
-        HObjectAccess::ForHeapNumberValue(), NULL);
+    return New<HLoadNamedField>(heap_number,
+                                HObjectAccess::ForHeapNumberValue(),
+                                typecheck);
+  }
+  return New<HLoadNamedField>(object, access, typecheck);
+}
+
+
+HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
+                                                   HValue* typecheck) {
+  if (FLAG_fold_constants && object->IsConstant()) {
+    HConstant* constant = HConstant::cast(object);
+    if (constant->HasStringValue()) {
+      return New<HConstant>(constant->StringValue()->length());
+    }
   }
-  return new(zone()) HLoadNamedField(object, access, NULL);
+  return BuildLoadNamedField(
+      object, HObjectAccess::ForStringLength(), typecheck);
 }
 
 
@@ -5376,7 +5272,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
   if (expr->IsUninitialized()) {
     Add<HDeoptimize>(Deoptimizer::SOFT);
   }
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   return new(zone()) HLoadNamedGeneric(context, object, name);
 }
 
@@ -5403,8 +5299,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
   // Handle access to various length properties
   if (name->Equals(isolate()->heap()->length_string())) {
     if (map->instance_type() == JS_ARRAY_TYPE) {
-      AddCheckMapsWithTransitions(object, map);
-      return new(zone()) HLoadNamedField(object,
+      AddCheckMap(object, map);
+      return New<HLoadNamedField>(object,
           HObjectAccess::ForArrayLength(map->elements_kind()));
     }
   }
@@ -5421,7 +5317,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
   if (lookup.IsConstant()) {
     AddCheckMap(object, map);
     Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
-    return new(zone()) HConstant(constant);
+    return New<HConstant>(constant);
   }
 
   // Handle a load from a known field somewhere in the prototype chain.
@@ -5431,7 +5327,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
     Handle<JSObject> holder(lookup.holder());
     Handle<Map> holder_map(holder->map());
     AddCheckMap(object, map);
-    Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
+    BuildCheckPrototypeMaps(prototype, holder);
     HValue* holder_value = Add<HConstant>(holder);
     return BuildLoadNamedField(holder_value,
         HObjectAccess::ForField(holder_map, &lookup, name));
@@ -5443,9 +5339,9 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
     Handle<JSObject> holder(lookup.holder());
     Handle<Map> holder_map(holder->map());
     AddCheckMap(object, map);
-    Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
+    BuildCheckPrototypeMaps(prototype, holder);
     Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
-    return new(zone()) HConstant(constant);
+    return New<HConstant>(constant);
   }
 
   // No luck, do a generic load.
@@ -5455,7 +5351,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
 
 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
                                                             HValue* key) {
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   return new(zone()) HLoadKeyedGeneric(context, object, key);
 }
 
@@ -5468,9 +5364,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
     Handle<Map> map,
     bool is_store,
     KeyedAccessStoreMode store_mode) {
-  HCheckMaps* mapcheck = HCheckMaps::New(
-      object, map, zone(), top_info(), dependency);
-  AddInstruction(mapcheck);
+  HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency);
   if (dependency) {
     mapcheck->ClearGVNFlag(kDependsOnElementsKind);
   }
@@ -5481,7 +5375,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
-    Add<HCheckPrototypeMaps>(prototype, object_prototype, zone(), top_info());
+    BuildCheckPrototypeMaps(prototype, object_prototype);
     load_mode = ALLOW_RETURN_HOLE;
     graph()->MarkDependsOnEmptyArrayProtoElements();
   }
@@ -5538,8 +5432,7 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
   }
   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
 
-  HCheckMaps* check_maps = HCheckMaps::New(object, maps, zone());
-  AddInstruction(check_maps);
+  HCheckMaps* check_maps = Add<HCheckMaps>(object, maps);
   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
       object, key, val, check_maps,
       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
@@ -5604,8 +5497,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
       ASSERT(Map::IsValidElementsTransition(
           map->elements_kind(),
           transition_target.at(i)->elements_kind()));
-      HValue* context = environment()->LookupContext();
-      transition = Add<HTransitionElementsKind>(context, object, map,
+      transition = Add<HTransitionElementsKind>(object, map,
                                                 transition_target.at(i));
     } else {
       untransitionable_maps.Add(map);
@@ -5651,12 +5543,12 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
     HInstruction* access = NULL;
     if (IsFastElementsKind(elements_kind)) {
       if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
-        AddInstruction(HCheckMaps::New(
+        Add<HCheckMaps>(
             elements, isolate()->factory()->fixed_array_map(),
-            zone(), top_info(), mapcompare));
+            top_info(), mapcompare);
       }
       if (map->instance_type() == JS_ARRAY_TYPE) {
-        HInstruction* length = AddLoad(
+        HInstruction* length = Add<HLoadNamedField>(
             object, HObjectAccess::ForArrayLength(elements_kind), mapcompare);
         checked_key = Add<HBoundsCheck>(key, length);
       } else {
@@ -5752,7 +5644,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
     HValue* object,
     HValue* key,
     HValue* value) {
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   return new(zone()) HStoreKeyedGeneric(
                          context,
                          object,
@@ -5778,13 +5670,12 @@ void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
   HInstruction* insert_after = entry;
   for (int i = 0; i < arguments_values->length(); i++) {
     HValue* argument = arguments_values->at(i);
-    HInstruction* push_argument = new(zone()) HPushArgument(argument);
+    HInstruction* push_argument = New<HPushArgument>(argument);
     push_argument->InsertAfter(insert_after);
     insert_after = push_argument;
   }
 
-  HArgumentsElements* arguments_elements =
-      new(zone()) HArgumentsElements(true);
+  HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
   arguments_elements->ClearFlag(HValue::kUseGVN);
   arguments_elements->InsertAfter(insert_after);
   function_state()->set_arguments_elements(arguments_elements);
@@ -5806,12 +5697,12 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
 
     if (function_state()->outer() == NULL) {
       HInstruction* elements = Add<HArgumentsElements>(false);
-      result = new(zone()) HArgumentsLength(elements);
+      result = New<HArgumentsLength>(elements);
     } else {
       // Number of arguments without receiver.
       int argument_count = environment()->
           arguments_environment()->parameter_count() - 1;
-      result = new(zone()) HConstant(argument_count);
+      result = New<HConstant>(argument_count);
     }
   } else {
     Push(graph()->GetArgumentsObject());
@@ -5854,15 +5745,16 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
   if (expr->IsStringLength()) {
     HValue* string = Pop();
     BuildCheckHeapObject(string);
-    AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
-    instr = HStringLength::New(zone(), string);
+    HInstruction* checkstring =
+        AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
+    instr = BuildLoadStringLength(string, checkstring);
   } else if (expr->IsStringAccess()) {
     CHECK_ALIVE(VisitForValue(expr->key()));
     HValue* index = Pop();
     HValue* string = Pop();
-    HValue* context = environment()->LookupContext();
+    HValue* context = environment()->context();
     HInstruction* char_code =
-      BuildStringCharCodeAt(context, string, index);
+      BuildStringCharCodeAt(string, index);
     AddInstruction(char_code);
     instr = HStringCharFromCode::New(zone(), context, char_code);
 
@@ -5929,11 +5821,38 @@ 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()));
-    Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
+    BuildCheckPrototypeMaps(prototype, holder);
   }
 }
 
@@ -5945,7 +5864,7 @@ void HOptimizedGraphBuilder::AddCheckConstantFunction(
   // Constant functions have the nice property that the map will change if they
   // are overwritten.  Therefore it is enough to check the map of the holder and
   // its prototypes.
-  AddCheckMapsWithTransitions(receiver, receiver_map);
+  AddCheckMap(receiver, receiver_map);
   AddCheckPrototypeMaps(holder, receiver_map);
 }
 
@@ -6002,7 +5921,7 @@ bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
   if (!expr->ComputeTarget(map, name)) return false;
 
   BuildCheckHeapObject(receiver);
-  AddInstruction(HCheckMaps::New(receiver, types, zone()));
+  Add<HCheckMaps>(receiver, types);
   AddCheckPrototypeMaps(expr->holder(), map);
   if (FLAG_trace_inlining) {
     Handle<JSFunction> caller = current_info()->closure();
@@ -6158,7 +6077,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
     Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1));
     FinishExitWithHardDeoptimization(join);
   } else {
-    HValue* context = environment()->LookupContext();
+    HValue* context = environment()->context();
     HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
     call->set_position(expr->position());
     PreProcessCall(call);
@@ -6305,7 +6224,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("parse/scope error");
+      target_shared->DisableOptimization(kParseScopeError);
     }
     TraceInline(target, caller, "parse failure");
     return false;
@@ -6424,7 +6343,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
     ASSERT(function->scope()->arguments()->IsStackAllocated());
     HEnvironment* arguments_env = inner_env->arguments_environment();
     int arguments_count = arguments_env->parameter_count();
-    arguments_object = Add<HArgumentsObject>(arguments_count, zone());
+    arguments_object = Add<HArgumentsObject>(arguments_count);
     inner_env->Bind(function->scope()->arguments(), arguments_object);
     for (int i = 0; i < arguments_count; i++) {
       arguments_object->AddArgument(arguments_env->Lookup(i), zone());
@@ -6435,7 +6354,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
       Add<HEnterInlined>(target, arguments_count, function,
                          function_state()->inlining_kind(),
                          function->scope()->arguments(),
-                         arguments_object, undefined_receiver, zone());
+                         arguments_object, undefined_receiver);
   function_state()->set_entry(enter_inlined);
 
   VisitDeclarations(target_info.scope()->declarations());
@@ -6444,7 +6363,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("inlining bailed out");
+    target_shared->DisableOptimization(kInliningBailedOut);
     inline_bailout_ = true;
     delete target_state;
     return true;
@@ -6626,7 +6545,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr,
     case kMathTan:
       if (expr->arguments()->length() == 1) {
         HValue* argument = Pop();
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         Drop(1);  // Receiver.
         HInstruction* op =
             HUnaryMathOperation::New(zone(), context, argument, id);
@@ -6641,7 +6560,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr,
         HValue* right = Pop();
         HValue* left = Pop();
         Drop(1);  // Receiver.
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HInstruction* op = HMul::NewImul(zone(), context, left, right);
         if (drop_extra) Drop(1);  // Optionally drop the function.
         ast_context()->ReturnInstruction(op, expr->id());
@@ -6672,13 +6591,13 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
       if (argument_count == 2 && check_type == STRING_CHECK) {
         HValue* index = Pop();
         HValue* string = Pop();
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         ASSERT(!expr->holder().is_null());
-        Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck(
+        BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
                 STRING_CHECK, expr->holder()->GetIsolate()),
-            expr->holder(), zone(), top_info());
+            expr->holder());
         HInstruction* char_code =
-            BuildStringCharCodeAt(context, string, index);
+            BuildStringCharCodeAt(string, index);
         if (id == kStringCharCodeAt) {
           ast_context()->ReturnInstruction(char_code, expr->id());
           return true;
@@ -6694,7 +6613,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
       if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
         AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
         HValue* argument = Pop();
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         Drop(1);  // Receiver.
         HInstruction* result =
             HStringCharFromCode::New(zone(), context, argument);
@@ -6716,7 +6635,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
       if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
         AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
         HValue* argument = Pop();
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         Drop(1);  // Receiver.
         HInstruction* op =
             HUnaryMathOperation::New(zone(), context, argument, id);
@@ -6731,7 +6650,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
         HValue* right = Pop();
         HValue* left = Pop();
         Pop();  // Pop receiver.
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HInstruction* result = NULL;
         // Use sqrt() if exponent is 0.5 or -0.5.
         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
@@ -6756,7 +6675,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
         }
 
         if (result == NULL) {
-          result = HPower::New(zone(), left, right);
+          result = HPower::New(zone(), context, left, right);
         }
         ast_context()->ReturnInstruction(result, expr->id());
         return true;
@@ -6766,8 +6685,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
       if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
         AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
         Drop(1);  // Receiver.
-        HValue* context = environment()->LookupContext();
-        HGlobalObject* global_object = Add<HGlobalObject>(context);
+        HGlobalObject* global_object = Add<HGlobalObject>();
         HRandom* result = new(zone()) HRandom(global_object);
         ast_context()->ReturnInstruction(result, expr->id());
         return true;
@@ -6780,7 +6698,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
         HValue* right = Pop();
         HValue* left = Pop();
         Drop(1);  // Receiver.
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
                                                      : HMathMinMax::kMathMax;
         HInstruction* result =
@@ -6795,7 +6713,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
         HValue* right = Pop();
         HValue* left = Pop();
         Drop(1);  // Receiver.
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HInstruction* result = HMul::NewImul(zone(), context, left, right);
         ast_context()->ReturnInstruction(result, expr->id());
         return true;
@@ -6879,12 +6797,12 @@ bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
     }
 
     Drop(arguments_count - 1);
-    PushAndAdd(new(zone()) HPushArgument(Pop()));
+    PushAndAdd(New<HPushArgument>(Pop()));
     for (int i = 1; i < arguments_count; i++) {
-      PushAndAdd(new(zone()) HPushArgument(arguments_values->at(i)));
+      PushAndAdd(New<HPushArgument>(arguments_values->at(i)));
     }
 
-    HValue* context = environment()->LookupContext();
+    HValue* context = environment()->context();
     HInvokeFunction* call = new(zone()) HInvokeFunction(
         context,
         function,
@@ -6898,55 +6816,6 @@ bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
 }
 
 
-// Checks if all maps in |types| are from the same family, i.e., are elements
-// transitions of each other. Returns either NULL if they are not from the same
-// family, or a Map* indicating the map with the first elements kind of the
-// family that is in the list.
-static Map* CheckSameElementsFamily(SmallMapList* types) {
-  if (types->length() <= 1) return NULL;
-  // Check if all maps belong to the same transition family.
-  Map* kinds[kFastElementsKindCount];
-  Map* first_map = *types->first();
-  ElementsKind first_kind = first_map->elements_kind();
-  if (!IsFastElementsKind(first_kind)) return NULL;
-  int first_index = GetSequenceIndexFromFastElementsKind(first_kind);
-  int last_index = first_index;
-
-  for (int i = 0; i < kFastElementsKindCount; i++) kinds[i] = NULL;
-
-  kinds[first_index] = first_map;
-
-  for (int i = 1; i < types->length(); ++i) {
-    Map* map = *types->at(i);
-    ElementsKind elements_kind = map->elements_kind();
-    if (!IsFastElementsKind(elements_kind)) return NULL;
-    int index = GetSequenceIndexFromFastElementsKind(elements_kind);
-    if (index < first_index) {
-      first_index = index;
-    } else if (index > last_index) {
-      last_index = index;
-    } else if (kinds[index] != map) {
-      return NULL;
-    }
-    kinds[index] = map;
-  }
-
-  Map* current = kinds[first_index];
-  for (int i = first_index + 1; i <= last_index; i++) {
-    Map* next = kinds[i];
-    if (next != NULL) {
-      ElementsKind current_kind = next->elements_kind();
-      if (next != current->LookupElementsTransitionMap(current_kind)) {
-        return NULL;
-      }
-      current = next;
-    }
-  }
-
-  return kinds[first_index];
-}
-
-
 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
@@ -6970,7 +6839,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
 
       CHECK_ALIVE(VisitArgumentList(expr->arguments()));
 
-      HValue* context = environment()->LookupContext();
+      HValue* context = environment()->context();
       call = new(zone()) HCallKeyed(context, key, argument_count);
       call->set_position(expr->position());
       Drop(argument_count + 1);  // 1 is the key.
@@ -6992,12 +6861,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
       receiver_map = (types == NULL || types->is_empty())
           ? Handle<Map>::null()
           : types->first();
-    } else {
-      Map* family_map = CheckSameElementsFamily(types);
-      if (family_map != NULL) {
-        receiver_map = Handle<Map>(family_map);
-        monomorphic = expr->ComputeTarget(receiver_map, name);
-      }
     }
 
     HValue* receiver =
@@ -7020,7 +6883,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
         // When the target has a custom call IC generator, use the IC,
         // because it is likely to generate better code.  Also use the IC
         // when a primitive receiver check is required.
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         call = PreProcessCall(
             new(zone()) HCallNamed(context, name, argument_count));
       } else {
@@ -7037,7 +6900,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
       return;
 
     } else {
-      HValue* context = environment()->LookupContext();
+      HValue* context = environment()->context();
       call = PreProcessCall(
           new(zone()) HCallNamed(context, name, argument_count));
     }
@@ -7045,7 +6908,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
   } else {
     VariableProxy* proxy = expr->expression()->AsVariableProxy();
     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
-      return Bailout("possible direct call to eval");
+      return Bailout(kPossibleDirectCallToEval);
     }
 
     bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
@@ -7065,7 +6928,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
       if (known_global_function) {
         // Push the global object instead of the global receiver because
         // code generated by the full code generator expects it.
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HGlobalObject* global_object = new(zone()) HGlobalObject(context);
         PushAndAdd(global_object);
         CHECK_ALIVE(VisitExpressions(expr->arguments()));
@@ -7099,7 +6962,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
         if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
           // When the target has a custom call IC generator, use the IC,
           // because it is likely to generate better code.
-          HValue* context = environment()->LookupContext();
+          HValue* context = environment()->context();
           call = PreProcessCall(
               new(zone()) HCallNamed(context, var->name(), argument_count));
         } else {
@@ -7107,12 +6970,11 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
                                                            argument_count));
         }
       } else {
-        HValue* context = environment()->LookupContext();
-        HGlobalObject* receiver = Add<HGlobalObject>(context);
-        PushAndAdd(new(zone()) HPushArgument(receiver));
+        HGlobalObject* receiver = Add<HGlobalObject>();
+        PushAndAdd(New<HPushArgument>(receiver));
         CHECK_ALIVE(VisitArgumentList(expr->arguments()));
 
-        call = new(zone()) HCallGlobal(context, var->name(), argument_count);
+        call = New<HCallGlobal>(var->name(), argument_count);
         Drop(argument_count);
       }
 
@@ -7121,9 +6983,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
       // evaluation of the arguments.
       CHECK_ALIVE(VisitForValue(expr->expression()));
       HValue* function = Top();
-      HValue* context = environment()->LookupContext();
-      HGlobalObject* global = Add<HGlobalObject>(context);
-      HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
+      HGlobalObject* global = Add<HGlobalObject>();
+      HGlobalReceiver* receiver = New<HGlobalReceiver>(global);
       PushAndAdd(receiver);
       CHECK_ALIVE(VisitExpressions(expr->arguments()));
       Add<HCheckFunction>(function, expr->target());
@@ -7140,24 +7001,20 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
       if (TryInlineCall(expr, true)) {   // Drop function from environment.
         return;
       } else {
-        call = PreProcessCall(
-            new(zone()) HInvokeFunction(context,
-                                        function,
-                                        expr->target(),
-                                        argument_count));
+        call = PreProcessCall(New<HInvokeFunction>(function, expr->target(),
+                                                   argument_count));
         Drop(1);  // The function.
       }
 
     } else {
       CHECK_ALIVE(VisitForValue(expr->expression()));
       HValue* function = Top();
-      HValue* context = environment()->LookupContext();
-      HGlobalObject* global_object = Add<HGlobalObject>(context);
+      HGlobalObject* global_object = Add<HGlobalObject>();
       HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object);
-      PushAndAdd(new(zone()) HPushArgument(receiver));
+      PushAndAdd(New<HPushArgument>(receiver));
       CHECK_ALIVE(VisitArgumentList(expr->arguments()));
 
-      call = new(zone()) HCallFunction(context, function, argument_count);
+      call = New<HCallFunction>(function, argument_count);
       Drop(argument_count + 1);
     }
   }
@@ -7181,7 +7038,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   Factory* factory = isolate()->factory();
 
   if (FLAG_inline_construct &&
@@ -7209,42 +7066,41 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
 
     // Allocate an instance of the implicit receiver object.
     HValue* size_in_bytes = Add<HConstant>(instance_size);
-    HAllocate::Flags flags = HAllocate::DefaultFlags();
-    if (FLAG_pretenuring_call_new &&
-        isolate()->heap()->ShouldGloballyPretenure()) {
-      flags = static_cast<HAllocate::Flags>(
-          flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
-    }
+    PretenureFlag pretenure_flag =
+        (FLAG_pretenuring_call_new &&
+            isolate()->heap()->GetPretenureMode() == TENURED)
+                ? TENURED : NOT_TENURED;
     HAllocate* receiver =
-        Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags);
+        Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure_flag,
+        JS_OBJECT_TYPE);
     receiver->set_known_initial_map(initial_map);
 
     // Load the initial map from the constructor.
     HValue* constructor_value = Add<HConstant>(constructor);
     HValue* initial_map_value =
-        AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset(
+      Add<HLoadNamedField>(constructor_value, HObjectAccess::ForJSObjectOffset(
             JSFunction::kPrototypeOrInitialMapOffset));
 
     // Initialize map and fields of the newly allocated object.
     { NoObservableSideEffectsScope no_effects(this);
       ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
-      AddStore(receiver,
-               HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
-               initial_map_value);
+      Add<HStoreNamedField>(receiver,
+          HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
+          initial_map_value);
       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
-      AddStore(receiver,
-               HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
-               empty_fixed_array);
-      AddStore(receiver,
-               HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset),
-               empty_fixed_array);
+      Add<HStoreNamedField>(receiver,
+          HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
+          empty_fixed_array);
+      Add<HStoreNamedField>(receiver,
+          HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset),
+          empty_fixed_array);
       if (initial_map->inobject_properties() != 0) {
         HConstant* undefined = graph()->GetConstantUndefined();
         for (int i = 0; i < initial_map->inobject_properties(); i++) {
           int property_offset = JSObject::kHeaderSize + i * kPointerSize;
-          AddStore(receiver,
-                   HObjectAccess::ForJSObjectOffset(property_offset),
-                   undefined);
+          Add<HStoreNamedField>(receiver,
+              HObjectAccess::ForJSObjectOffset(property_offset),
+              undefined);
         }
       }
     }
@@ -7320,7 +7176,7 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   if (expr->is_jsruntime()) {
-    return Bailout("call to a JavaScript runtime function");
+    return Bailout(kCallToAJavaScriptRuntimeFunction);
   }
 
   const Runtime::Function* function = expr->function();
@@ -7342,11 +7198,10 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
     ASSERT(function->intrinsic_type == Runtime::RUNTIME);
     CHECK_ALIVE(VisitArgumentList(expr->arguments()));
 
-    HValue* context = environment()->LookupContext();
     Handle<String> name = expr->name();
     int argument_count = expr->arguments()->length();
-    HCallRuntime* call =
-        new(zone()) HCallRuntime(context, name, function, argument_count);
+    HCallRuntime* call = New<HCallRuntime>(name, function,
+                                           argument_count);
     Drop(argument_count);
     return ast_context()->ReturnInstruction(call, expr->id());
   }
@@ -7361,8 +7216,6 @@ 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();
   }
@@ -7377,19 +7230,18 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
     CHECK_ALIVE(VisitForValue(prop->key()));
     HValue* key = Pop();
     HValue* obj = Pop();
-    HValue* context = environment()->LookupContext();
-    HValue* function = AddLoadJSBuiltin(Builtins::DELETE, context);
+    HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
     Add<HPushArgument>(obj);
     Add<HPushArgument>(key);
     Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag()));
     // TODO(olivf) InvokeFunction produces a check for the parameter count,
     // even though we are certain to pass the correct number of arguments here.
-    HInstruction* instr = new(zone()) HInvokeFunction(context, function, 3);
+    HInstruction* instr = New<HInvokeFunction>(function, 3);
     return ast_context()->ReturnInstruction(instr, expr->id());
   } else if (proxy != NULL) {
     Variable* var = proxy->var();
     if (var->IsUnallocated()) {
-      Bailout("delete with global variable");
+      Bailout(kDeleteWithGlobalVariable);
     } 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
@@ -7399,7 +7251,7 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
           : graph()->GetConstantFalse();
       return ast_context()->ReturnValue(value);
     } else {
-      Bailout("delete with non-global variable");
+      Bailout(kDeleteWithNonGlobalVariable);
     }
   } else {
     // Result of deleting non-property, non-variable reference is true.
@@ -7419,30 +7271,12 @@ void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
   HValue* value = Pop();
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HInstruction* instr = new(zone()) HTypeof(context, value);
   return ast_context()->ReturnInstruction(instr, expr->id());
 }
 
 
-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());
@@ -7516,11 +7350,9 @@ HInstruction* HOptimizedGraphBuilder::BuildIncrement(
   HConstant* delta = (expr->op() == Token::INC)
       ? graph()->GetConstant1()
       : graph()->GetConstantMinus1();
-  HValue* context = environment()->LookupContext();
-  HInstruction* instr = HAdd::New(zone(), context, Top(), delta);
+  HInstruction* instr = Add<HAdd>(Top(), delta);
   instr->SetFlag(HInstruction::kCannotBeTagged);
   instr->ClearAllSideEffects();
-  AddInstruction(instr);
   return instr;
 }
 
@@ -7533,7 +7365,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   VariableProxy* proxy = target->AsVariableProxy();
   Property* prop = target->AsProperty();
   if (proxy == NULL && prop == NULL) {
-    return Bailout("invalid lhs in count operation");
+    return Bailout(kInvalidLhsInCountOperation);
   }
 
   // Match the full code generator stack by simulating an extra stack
@@ -7547,7 +7379,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   if (proxy != NULL) {
     Variable* var = proxy->var();
     if (var->mode() == CONST)  {
-      return Bailout("unsupported count operation with const");
+      return Bailout(kUnsupportedCountOperationWithConst);
     }
     // Argument of the count operation is a variable, not a property.
     ASSERT(prop == NULL);
@@ -7581,7 +7413,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("assignment to parameter in arguments object");
+              return Bailout(kAssignmentToParameterInArgumentsObject);
             }
           }
         }
@@ -7598,7 +7430,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
       }
 
       case Variable::LOOKUP:
-        return Bailout("lookup variable in count operation");
+        return Bailout(kLookupVariableInCountOperation);
     }
 
   } else {
@@ -7685,7 +7517,6 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
 
 
 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
-    HValue* context,
     HValue* string,
     HValue* index) {
   if (string->IsConstant() && index->IsConstant()) {
@@ -7695,17 +7526,18 @@ HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
       int32_t i = c_index->NumberValueAsInteger32();
       Handle<String> s = c_string->StringValue();
       if (i < 0 || i >= s->length()) {
-        return new(zone()) HConstant(OS::nan_value());
+        return New<HConstant>(OS::nan_value());
       }
-      return new(zone()) HConstant(s->Get(i));
+      return New<HConstant>(s->Get(i));
     }
   }
   BuildCheckHeapObject(string);
-  AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
-  HInstruction* length = HStringLength::New(zone(), string);
+  HValue* checkstring =
+      AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
+  HInstruction* length = BuildLoadStringLength(string, checkstring);
   AddInstruction(length);
   HInstruction* checked_index = Add<HBoundsCheck>(index, length);
-  return new(zone()) HStringCharCodeAt(context, string, checked_index);
+  return New<HStringCharCodeAt>(string, checked_index);
 }
 
 
@@ -7775,26 +7607,6 @@ HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) {
       *expected = handle(Type::Number(), isolate());
       return AddInstruction(number.value);
     }
-    return value;
-  }
-
-  Handle<Type> expected_type = *expected;
-  Representation rep = Representation::FromType(expected_type);
-  if (!rep.IsTagged()) return value;
-
-  // If our type feedback suggests that we can non-observably truncate to number
-  // we introduce the appropriate check here. This avoids 'value' having a
-  // tagged representation later on.
-  if (expected_type->Is(Type::Oddball())) {
-    // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to
-    // also record booleans and convert them to 0/1 here.
-    IfBuilder if_nan(this);
-    if_nan.If<HCompareObjectEqAndBranch>(value,
-        graph()->GetConstantUndefined());
-    if_nan.Then();
-    if_nan.ElseDeopt();
-    if_nan.End();
-    return Add<HConstant>(OS::nan_value(), Representation::Double());
   }
 
   return value;
@@ -7805,7 +7617,7 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
     BinaryOperation* expr,
     HValue* left,
     HValue* right) {
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   Handle<Type> left_type = expr->left()->bounds().lower;
   Handle<Type> right_type = expr->right()->bounds().lower;
   Handle<Type> result_type = expr->bounds().lower;
@@ -7858,7 +7670,7 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
       break;
     case Token::BIT_XOR:
     case Token::BIT_AND:
-      instr = HBitwise::New(zone(), expr->op(), context, left, right);
+      instr = NewUncasted<HBitwise>(expr->op(), left, right);
       break;
     case Token::BIT_OR: {
       HValue* operand, *shift_amount;
@@ -7867,7 +7679,7 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
           MatchRotateRight(left, right, &operand, &shift_amount)) {
         instr = new(zone()) HRor(context, operand, shift_amount);
       } else {
-        instr = HBitwise::New(zone(), expr->op(), context, left, right);
+        instr = NewUncasted<HBitwise>(expr->op(), left, right);
       }
       break;
     }
@@ -8112,14 +7924,14 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   CHECK_ALIVE(VisitForValue(expr->left()));
   CHECK_ALIVE(VisitForValue(expr->right()));
 
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HValue* right = Pop();
   HValue* left = Pop();
   Token::Value op = expr->op();
 
   if (IsLiteralCompareBool(left, op, right)) {
     HCompareObjectEqAndBranch* result =
-        new(zone()) HCompareObjectEqAndBranch(left, right);
+        New<HCompareObjectEqAndBranch>(left, right);
     result->set_position(expr->position());
     return ast_context()->ReturnControl(result, expr->id());
   }
@@ -8165,7 +7977,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
     // Code below assumes that we don't fall through.
     UNREACHABLE();
   } else if (op == Token::IN) {
-    HValue* function = AddLoadJSBuiltin(Builtins::IN, context);
+    HValue* function = AddLoadJSBuiltin(Builtins::IN);
     Add<HPushArgument>(left);
     Add<HPushArgument>(right);
     // TODO(olivf) InvokeFunction produces a check for the parameter count,
@@ -8189,10 +8001,10 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
         // Can we get away with map check and not instance type check?
         if (combined_type->IsClass()) {
           Handle<Map> map = combined_type->AsClass();
-          AddCheckMapsWithTransitions(left, map);
-          AddCheckMapsWithTransitions(right, map);
+          AddCheckMap(left, map);
+          AddCheckMap(right, map);
           HCompareObjectEqAndBranch* result =
-              new(zone()) HCompareObjectEqAndBranch(left, right);
+              New<HCompareObjectEqAndBranch>(left, right);
           result->set_position(expr->position());
           return ast_context()->ReturnControl(result, expr->id());
         } else {
@@ -8207,7 +8019,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
         }
       }
       default:
-        return Bailout("Unsupported non-primitive compare");
+        return Bailout(kUnsupportedNonPrimitiveCompare);
     }
   } else if (combined_type->Is(Type::InternalizedString()) &&
              Token::IsEqualityOp(op)) {
@@ -8273,7 +8085,7 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
   // If we share optimized code between different closures, the
   // this-function is not a constant, except inside an inlined body.
   if (function_state()->outer() != NULL) {
-      return new(zone()) HConstant(
+      return New<HConstant>(
           function_state()->compilation_info()->closure());
   } else {
       return new(zone()) HThisFunction;
@@ -8294,34 +8106,27 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
   HInstruction* target = NULL;
   HInstruction* data_target = NULL;
 
-  ElementsKind kind = boilerplate_object->map()->elements_kind();
-
-  if (isolate()->heap()->ShouldGloballyPretenure()) {
+  if (isolate()->heap()->GetPretenureMode() == TENURED) {
     if (data_size != 0) {
-      HAllocate::Flags data_flags =
-          static_cast<HAllocate::Flags>(HAllocate::DefaultFlags(kind) |
-              HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
       HValue* size_in_bytes = Add<HConstant>(data_size);
-      data_target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(),
-          data_flags);
+      data_target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED,
+          FIXED_DOUBLE_ARRAY_TYPE);
       Handle<Map> free_space_map = isolate()->factory()->free_space_map();
       AddStoreMapConstant(data_target, free_space_map);
       HObjectAccess access =
           HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset);
-      AddStore(data_target, access, size_in_bytes);
+      Add<HStoreNamedField>(data_target, access, size_in_bytes);
     }
     if (pointer_size != 0) {
-      HAllocate::Flags pointer_flags =
-          static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() |
-              HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
       HValue* size_in_bytes = Add<HConstant>(pointer_size);
-      target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(),
-          pointer_flags);
+      target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED,
+          JS_OBJECT_TYPE);
     }
   } else {
-    HAllocate::Flags flags = HAllocate::DefaultFlags(kind);
+    InstanceType instance_type = boilerplate_object->map()->instance_type();
     HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size);
-    target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags);
+    target = Add<HAllocate>(size_in_bytes, HType::JSObject(), NOT_TENURED,
+        instance_type);
   }
 
   int offset = 0;
@@ -8342,8 +8147,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
     HInstruction* data_target,
     int* data_offset,
     AllocationSiteMode mode) {
-  Zone* zone = this->zone();
-
   bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
       boilerplate_object->map()->CanTrackAllocationSite();
 
@@ -8355,8 +8158,7 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
   HInstruction* allocation_site = NULL;
 
   if (create_allocation_site_info) {
-    allocation_site = AddInstruction(new(zone) HConstant(
-        allocation_site_object, Representation::Tagged()));
+    allocation_site = Add<HConstant>(allocation_site_object);
   }
 
   // Only elements backing stores for non-COW arrays need to be copied.
@@ -8437,14 +8239,15 @@ HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader(
     }
     result = elements;
   }
-  AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
+  Add<HStoreNamedField>(object_header, HObjectAccess::ForElementsPointer(),
+                        elements);
 
   Handle<Object> properties_field =
       Handle<Object>(boilerplate_object->properties(), isolate());
   ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
   HInstruction* properties = Add<HConstant>(properties_field);
   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
-  AddStore(object_header, access, properties);
+  Add<HStoreNamedField>(object_header, access, properties);
 
   if (boilerplate_object->IsJSArray()) {
     Handle<JSArray> boilerplate_array =
@@ -8454,7 +8257,7 @@ HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader(
     HInstruction* length = Add<HConstant>(length_field);
 
     ASSERT(boilerplate_array->length()->IsSmi());
-    AddStore(object_header, HObjectAccess::ForArrayLength(
+    Add<HStoreNamedField>(object_header, HObjectAccess::ForArrayLength(
         boilerplate_array->GetElementsKind()), length);
   }
 
@@ -8499,7 +8302,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
       HInstruction* value_instruction = Add<HInnerAllocatedObject>(target,
                                                                    *offset);
 
-      AddStore(object_properties, access, value_instruction);
+      Add<HStoreNamedField>(object_properties, access, value_instruction);
       BuildEmitDeepCopy(value_object, original_value_object,
                         Handle<Object>::null(), target,
                         offset, data_target, data_offset,
@@ -8520,12 +8323,12 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
         }
         AddStoreMapConstant(double_box,
             isolate()->factory()->heap_number_map());
-        AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
+        Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
             value_instruction);
         value_instruction = double_box;
       }
 
-      AddStore(object_properties, access, value_instruction);
+      Add<HStoreNamedField>(object_properties, access, value_instruction);
     }
   }
 
@@ -8536,7 +8339,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
     ASSERT(boilerplate_object->IsJSObject());
     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
     HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset);
-    AddStore(object_properties, access, value_instruction);
+    Add<HStoreNamedField>(object_properties, access, value_instruction);
   }
 }
 
@@ -8645,7 +8448,7 @@ void HOptimizedGraphBuilder::VisitDeclarations(
     int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
         DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
-    Add<HDeclareGlobals>(environment()->LookupContext(), array, flags);
+    Add<HDeclareGlobals>(array, flags);
     globals_.Clear();
   }
 }
@@ -8674,7 +8477,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
     case Variable::CONTEXT:
       if (hole_init) {
         HValue* value = graph()->GetConstantHole();
-        HValue* context = environment()->LookupContext();
+        HValue* context = environment()->context();
         HStoreContextSlot* store = Add<HStoreContextSlot>(
             context, variable->index(), HStoreContextSlot::kNoCheck, value);
         if (store->HasObservableSideEffects()) {
@@ -8683,7 +8486,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
       }
       break;
     case Variable::LOOKUP:
-      return Bailout("unsupported lookup slot in declaration");
+      return Bailout(kUnsupportedLookupSlotInDeclaration);
   }
 }
 
@@ -8712,7 +8515,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
     case Variable::CONTEXT: {
       CHECK_ALIVE(VisitForValue(declaration->fun()));
       HValue* value = Pop();
-      HValue* context = environment()->LookupContext();
+      HValue* context = environment()->context();
       HStoreContextSlot* store = Add<HStoreContextSlot>(
           context, variable->index(), HStoreContextSlot::kNoCheck, value);
       if (store->HasObservableSideEffects()) {
@@ -8721,7 +8524,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
       break;
     }
     case Variable::LOOKUP:
-      return Bailout("unsupported lookup slot in declaration");
+      return Bailout(kUnsupportedLookupSlotInDeclaration);
   }
 }
 
@@ -8842,7 +8645,7 @@ void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
 
 
 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
-  return Bailout("inlined runtime function: IsNonNegativeSmi");
+  return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
 }
 
 
@@ -8858,8 +8661,7 @@ void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
 
 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
     CallRuntime* call) {
-  return Bailout(
-      "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
+  return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
 }
 
 
@@ -8887,7 +8689,7 @@ void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
   ASSERT(function_state()->outer() == NULL);
   ASSERT(call->arguments()->length() == 0);
   HInstruction* elements = Add<HArgumentsElements>(false);
-  HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
+  HArgumentsLength* result = New<HArgumentsLength>(elements);
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -8913,7 +8715,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("inlined runtime function: ClassOf");
+  return Bailout(kInlinedRuntimeFunctionClassOf);
 }
 
 
@@ -8996,7 +8798,7 @@ void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
 
   // Create in-object property store to kValueOffset.
   set_current_block(if_js_value);
-  AddStore(object,
+  Add<HStoreNamedField>(object,
       HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value);
   if_js_value->Goto(join);
   join->SetJoinId(call->id());
@@ -9012,8 +8814,7 @@ void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   HValue* index = Pop();
   HValue* string = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* result = BuildStringCharCodeAt(context, string, index);
+  HInstruction* result = BuildStringCharCodeAt(string, index);
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -9023,8 +8824,7 @@ void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
   ASSERT(call->arguments()->length() == 1);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   HValue* char_code = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* result = HStringCharFromCode::New(zone(), context, char_code);
+  HInstruction* result = New<HStringCharFromCode>(char_code);
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -9036,10 +8836,9 @@ void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   HValue* index = Pop();
   HValue* string = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* char_code = BuildStringCharCodeAt(context, string, index);
+  HInstruction* char_code = BuildStringCharCodeAt(string, index);
   AddInstruction(char_code);
-  HInstruction* result = HStringCharFromCode::New(zone(), context, char_code);
+  HInstruction* result = New<HStringCharFromCode>(char_code);
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -9052,7 +8851,7 @@ void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
   HValue* right = Pop();
   HValue* left = Pop();
   HCompareObjectEqAndBranch* result =
-      new(zone()) HCompareObjectEqAndBranch(left, right);
+      New<HCompareObjectEqAndBranch>(left, right);
   return ast_context()->ReturnControl(result, call->id());
 }
 
@@ -9065,8 +8864,7 @@ void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
 
 // Fast support for Math.random().
 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
-  HValue* context = environment()->LookupContext();
-  HGlobalObject* global_object = Add<HGlobalObject>(context);
+  HGlobalObject* global_object = Add<HGlobalObject>();
   HRandom* result = new(zone()) HRandom(global_object);
   return ast_context()->ReturnInstruction(result, call->id());
 }
@@ -9079,7 +8877,7 @@ void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   HValue* right = Pop();
   HValue* left = Pop();
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HInstruction* result = HStringAdd::New(
       zone(), context, left, right, STRING_ADD_CHECK_BOTH);
   return ast_context()->ReturnInstruction(result, call->id());
@@ -9090,7 +8888,7 @@ void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   ASSERT_EQ(3, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
   Drop(3);
   return ast_context()->ReturnInstruction(result, call->id());
@@ -9101,7 +8899,7 @@ void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
   ASSERT_EQ(2, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
   Drop(2);
@@ -9113,7 +8911,7 @@ void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
   ASSERT_EQ(4, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
   Drop(4);
   return ast_context()->ReturnInstruction(result, call->id());
@@ -9124,7 +8922,7 @@ void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
   ASSERT_EQ(3, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
   Drop(3);
@@ -9134,7 +8932,7 @@ void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
 
 // Support for fast native caches.
 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
-  return Bailout("inlined runtime function: GetFromCache");
+  return Bailout(kInlinedRuntimeFunctionGetFromCache);
 }
 
 
@@ -9142,7 +8940,7 @@ void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
   ASSERT_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
   Drop(1);
@@ -9162,7 +8960,6 @@ void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
   CHECK_ALIVE(VisitForValue(call->arguments()->last()));
 
   HValue* function = Pop();
-  HValue* context = environment()->LookupContext();
 
   // Branch for function proxies, or other non-functions.
   HHasInstanceTypeAndBranch* typecheck =
@@ -9175,14 +8972,13 @@ void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
   current_block()->Finish(typecheck);
 
   set_current_block(if_jsfunction);
-  HInstruction* invoke_result =
-      Add<HInvokeFunction>(context, function, arg_count);
+  HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count);
   Drop(arg_count);
   Push(invoke_result);
   if_jsfunction->Goto(join);
 
   set_current_block(if_nonfunction);
-  HInstruction* call_result = Add<HCallFunction>(context, function, arg_count);
+  HInstruction* call_result = Add<HCallFunction>(function, arg_count);
   Drop(arg_count);
   Push(call_result);
   if_nonfunction->Goto(join);
@@ -9200,7 +8996,7 @@ void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   HValue* right = Pop();
   HValue* left = Pop();
-  HInstruction* result = HPower::New(zone(), left, right);
+  HInstruction* result = HPower::New(zone(), context(), left, right);
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -9208,7 +9004,7 @@ void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) {
   ASSERT_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::SIN);
@@ -9220,7 +9016,7 @@ void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) {
   ASSERT_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::COS);
@@ -9232,7 +9028,7 @@ void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) {
   ASSERT_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::TAN);
@@ -9244,7 +9040,7 @@ void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) {
 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) {
   ASSERT_EQ(1, call->arguments()->length());
   CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HCallStub* result =
       new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::LOG);
@@ -9257,7 +9053,7 @@ void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
   ASSERT(call->arguments()->length() == 1);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   HValue* value = Pop();
-  HValue* context = environment()->LookupContext();
+  HValue* context = environment()->context();
   HInstruction* result =
       HUnaryMathOperation::New(zone(), context, value, kMathSqrt);
   return ast_context()->ReturnInstruction(result, call->id());
@@ -9266,7 +9062,7 @@ void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
 
 // Check whether two RegExps are equivalent
 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
-  return Bailout("inlined runtime function: IsRegExpEquivalent");
+  return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
 }
 
 
@@ -9280,18 +9076,18 @@ void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
 
 
 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
-  return Bailout("inlined runtime function: FastAsciiArrayJoin");
+  return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin);
 }
 
 
 // Support for generators.
 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
-  return Bailout("inlined runtime function: GeneratorNext");
+  return Bailout(kInlinedRuntimeFunctionGeneratorNext);
 }
 
 
 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
-  return Bailout("inlined runtime function: GeneratorThrow");
+  return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
 }
 
 
@@ -9567,7 +9363,7 @@ HEnvironment* HEnvironment::CopyForInlining(
   if (undefined_receiver) {
     inner->SetValueAt(0, undefined);
   }
-  inner->SetValueAt(arity + 1, LookupContext());
+  inner->SetValueAt(arity + 1, context());
   for (int i = arity + 2; i < inner->length(); ++i) {
     inner->SetValueAt(i, undefined);
   }
index 8484cd1..6312a52 100644 (file)
@@ -367,7 +367,7 @@ class HGraph: public ZoneObject {
     return NULL;
   }
 
-  bool Optimize(SmartArrayPointer<char>* bailout_reason);
+  bool Optimize(BailoutReason* bailout_reason);
 
 #ifdef DEBUG
   void Verify(bool do_full_verify) const;
@@ -583,7 +583,7 @@ class HEnvironment: public ZoneObject {
     return result;
   }
 
-  HValue* LookupContext() const {
+  HValue* context() const {
     // Return first special.
     return Lookup(parameter_count());
   }
@@ -990,57 +990,205 @@ class HGraphBuilder {
   void Push(HValue* value) { environment()->Push(value); }
   HValue* Pop() { return environment()->Pop(); }
 
+  virtual HValue* context() = 0;
+
   // Adding instructions.
   HInstruction* AddInstruction(HInstruction* instr);
 
   template<class I>
-  I* Add() { return static_cast<I*>(AddInstruction(new(zone()) I())); }
+  HInstruction* NewUncasted() { return I::New(zone(), context()); }
+
+  template<class I>
+  I* New() { return I::cast(NewUncasted<I>()); }
+
+  template<class I>
+  HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
+
+  template<class I>
+  I* Add() { return I::cast(AddUncasted<I>());}
+
+  template<class I, class P1>
+  HInstruction* NewUncasted(P1 p1) {
+    return I::New(zone(), context(), p1);
+  }
+
+  template<class I, class P1>
+  I* New(P1 p1) { return I::cast(NewUncasted<I>(p1)); }
+
+  template<class I, class P1>
+  HInstruction* AddUncasted(P1 p1) {
+    HInstruction* result = AddInstruction(NewUncasted<I>(p1));
+    // Specializations must have their parameters properly casted
+    // to avoid landing here.
+    ASSERT(!result->IsReturn() && !result->IsSimulate() &&
+           !result->IsDeoptimize());
+    return result;
+  }
 
   template<class I, class P1>
   I* Add(P1 p1) {
-    return static_cast<I*>(AddInstruction(new(zone()) I(p1)));
+    return I::cast(AddUncasted<I>(p1));
+  }
+
+  template<class I, class P1, class P2>
+  HInstruction* NewUncasted(P1 p1, P2 p2) {
+    return I::New(zone(), context(), p1, p2);
+  }
+
+  template<class I, class P1, class P2>
+  I* New(P1 p1, P2 p2) {
+    return I::cast(NewUncasted<I>(p1, p2));
+  }
+
+  template<class I, class P1, class P2>
+  HInstruction* AddUncasted(P1 p1, P2 p2) {
+    HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
+    // Specializations must have their parameters properly casted
+    // to avoid landing here.
+    ASSERT(!result->IsSimulate());
+    return result;
   }
 
   template<class I, class P1, class P2>
   I* Add(P1 p1, P2 p2) {
-      return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2)));
+    return static_cast<I*>(AddUncasted<I>(p1, p2));
+  }
+
+  template<class I, class P1, class P2, class P3>
+  HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
+    return I::New(zone(), context(), p1, p2, p3);
+  }
+
+  template<class I, class P1, class P2, class P3>
+  I* New(P1 p1, P2 p2, P3 p3) {
+    return I::cast(NewUncasted<I>(p1, p2, p3));
+  }
+
+  template<class I, class P1, class P2, class P3>
+  HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
+    return AddInstruction(NewUncasted<I>(p1, p2, p3));
   }
 
   template<class I, class P1, class P2, class P3>
   I* Add(P1 p1, P2 p2, P3 p3) {
-    return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2, p3)));
+    return I::cast(AddUncasted<I>(p1, p2, p3));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4>
+  HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
+    return I::New(zone(), context(), p1, p2, p3, p4);
+  }
+
+  template<class I, class P1, class P2, class P3, class P4>
+  I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
+    return I::cast(NewUncasted<I>(p1, p2, p3, p4));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4>
+  HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
+    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
   }
 
   template<class I, class P1, class P2, class P3, class P4>
   I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
-    return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2, p3, p4)));
+    return I::cast(AddUncasted<I>(p1, p2, p3, p4));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4, class P5>
+  HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+    return I::New(zone(), context(), p1, p2, p3, p4, p5);
+  }
+
+  template<class I, class P1, class P2, class P3, class P4, class P5>
+  I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+    return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4, class P5>
+  HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
   }
 
   template<class I, class P1, class P2, class P3, class P4, class P5>
   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
-    return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2, p3, p4, p5)));
+    return I::cast(AddUncasted<I>(p1, p2, p3, p4, p5));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
+  HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
+    return I::New(zone(), context(), p1, p2, p3, p4, p5, p6);
+  }
+
+  template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
+  I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
+    return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
+  HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
+    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
   }
 
   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
-    return static_cast<I*>(AddInstruction(
-            new(zone()) I(p1, p2, p3, p4, p5, p6)));
+    return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6)));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4,
+      class P5, class P6, class P7>
+  HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
+    return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7);
+  }
+
+  template<class I, class P1, class P2, class P3, class P4,
+      class P5, class P6, class P7>
+      I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
+    return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
+  }
+
+  template<class I, class P1, class P2, class P3,
+           class P4, class P5, class P6, class P7>
+  HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
+    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
   }
 
   template<class I, class P1, class P2, class P3,
            class P4, class P5, class P6, class P7>
   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
-    return static_cast<I*>(AddInstruction(
-            new(zone()) I(p1, p2, p3, p4, p5, p6, p7)));
+    return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4,
+                                                 p5, p6, p7)));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4,
+      class P5, class P6, class P7, class P8>
+  HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
+                            P5 p5, P6 p6, P7 p7, P8 p8) {
+    return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
+  }
+
+  template<class I, class P1, class P2, class P3, class P4,
+      class P5, class P6, class P7, class P8>
+      I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
+    return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
+  }
+
+  template<class I, class P1, class P2, class P3, class P4,
+           class P5, class P6, class P7, class P8>
+  HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
+                            P5 p5, P6 p6, P7 p7, P8 p8) {
+    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
   }
 
   template<class I, class P1, class P2, class P3, class P4,
            class P5, class P6, class P7, class P8>
   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
-    return static_cast<I*>(AddInstruction(
-            new(zone()) I(p1, p2, p3, p4, p5, p6, p7, p8)));
+    return I::cast(
+        AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)));
   }
 
+  void AddSimulate(BailoutId id,
+                   RemovableSimulate removable = FIXED_SIMULATE);
+
   void IncrementInNoSideEffectsScope() {
     no_side_effects_scope_count_++;
   }
@@ -1089,16 +1237,6 @@ class HGraphBuilder {
       LoadKeyedHoleMode load_mode,
       KeyedAccessStoreMode store_mode);
 
-  HLoadNamedField* AddLoad(
-      HValue *object,
-      HObjectAccess access,
-      HValue *typecheck = NULL);
-
-  HLoadNamedField* BuildLoadNamedField(
-      HValue* object,
-      HObjectAccess access,
-      Representation representation);
-
   HInstruction* AddExternalArrayElementAccess(
       HValue* external_elements,
       HValue* checked_key,
@@ -1117,13 +1255,16 @@ class HGraphBuilder {
       LoadKeyedHoleMode load_mode,
       KeyedAccessStoreMode store_mode);
 
-  HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access);
-  HStoreNamedField* AddStore(HValue *object, HObjectAccess access, HValue *val);
+  HLoadNamedField* BuildLoadNamedField(
+      HValue* object,
+      HObjectAccess access,
+      HValue* typecheck = NULL);
+  HInstruction* BuildLoadStringLength(HValue* object, HValue* typecheck = NULL);
   HStoreNamedField* AddStoreMapConstant(HValue *object, Handle<Map>);
   HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck = NULL);
   HLoadNamedField* AddLoadFixedArrayLength(HValue *object);
 
-  HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin, HValue* context);
+  HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin);
 
   HValue* TruncateToNumber(HValue* value, Handle<Type>* expected);
 
@@ -1314,8 +1455,7 @@ class HGraphBuilder {
     HGraphBuilder* builder_;
   };
 
-  HValue* BuildNewElementsCapacity(HValue* context,
-                                   HValue* old_capacity);
+  HValue* BuildNewElementsCapacity(HValue* old_capacity);
 
   void BuildNewSpaceArrayCheck(HValue* length,
                                ElementsKind kind);
@@ -1349,7 +1489,7 @@ class HGraphBuilder {
       return JSArray::kPreallocatedArrayElements;
     }
 
-    HValue* EmitMapCode(HValue* context);
+    HValue* EmitMapCode();
     HValue* EmitInternalMapCode();
     HValue* EstablishEmptyArrayAllocationSize();
     HValue* EstablishAllocationSize(HValue* length_node);
@@ -1364,16 +1504,14 @@ class HGraphBuilder {
     HInnerAllocatedObject* elements_location_;
   };
 
-  HValue* BuildAllocateElements(HValue* context,
-                                ElementsKind kind,
+  HValue* BuildAllocateElements(ElementsKind kind,
                                 HValue* capacity);
 
   void BuildInitializeElementsHeader(HValue* elements,
                                      ElementsKind kind,
                                      HValue* capacity);
 
-  HValue* BuildAllocateElementsAndInitializeElementsHeader(HValue* context,
-                                                           ElementsKind kind,
+  HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind,
                                                            HValue* capacity);
 
   // array must have been allocated with enough room for
@@ -1394,30 +1532,24 @@ class HGraphBuilder {
                                     HValue* length,
                                     HValue* new_capacity);
 
-  void BuildFillElementsWithHole(HValue* context,
-                                 HValue* elements,
+  void BuildFillElementsWithHole(HValue* elements,
                                  ElementsKind elements_kind,
                                  HValue* from,
                                  HValue* to);
 
-  void BuildCopyElements(HValue* context,
-                         HValue* from_elements,
+  void BuildCopyElements(HValue* from_elements,
                          ElementsKind from_elements_kind,
                          HValue* to_elements,
                          ElementsKind to_elements_kind,
                          HValue* length,
                          HValue* capacity);
 
-  HValue* BuildCloneShallowArray(HContext* context,
-                                 HValue* boilerplate,
+  HValue* BuildCloneShallowArray(HValue* boilerplate,
                                  HValue* allocation_site,
                                  AllocationSiteMode mode,
                                  ElementsKind kind,
                                  int length);
 
-  HInstruction* BuildUnaryMathOp(
-      HValue* value, Handle<Type> type, Token::Value token);
-
   void BuildCompareNil(
       HValue* value,
       Handle<Type> type,
@@ -1428,8 +1560,12 @@ class HGraphBuilder {
                                        int previous_object_size,
                                        HValue* payload);
 
-  HInstruction* BuildGetNativeContext(HValue* context);
-  HInstruction* BuildGetArrayFunction(HValue* context);
+  void BuildConstantMapCheck(Handle<JSObject> constant, CompilationInfo* info);
+  void BuildCheckPrototypeMaps(Handle<JSObject> prototype,
+                               Handle<JSObject> holder);
+
+  HInstruction* BuildGetNativeContext();
+  HInstruction* BuildGetArrayFunction();
 
  private:
   HGraphBuilder();
@@ -1445,13 +1581,14 @@ class HGraphBuilder {
 
 
 template<>
-inline HDeoptimize* HGraphBuilder::Add(Deoptimizer::BailoutType type) {
+inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
+    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(zone()) HDeoptimize(type);
+  HDeoptimize* instr = New<HDeoptimize>(type);
   AddInstruction(instr);
   if (type == Deoptimizer::SOFT) {
     isolate()->counters()->soft_deopts_inserted()->Increment();
@@ -1463,8 +1600,16 @@ inline HDeoptimize* HGraphBuilder::Add(Deoptimizer::BailoutType type) {
 
 
 template<>
-inline HSimulate* HGraphBuilder::Add(BailoutId id,
-                                     RemovableSimulate removable) {
+inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
+    Deoptimizer::BailoutType type) {
+  return static_cast<HDeoptimize*>(AddUncasted<HDeoptimize>(type));
+}
+
+
+template<>
+inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(
+    BailoutId id,
+    RemovableSimulate removable) {
   HSimulate* instr = current_block()->CreateSimulate(id, removable);
   AddInstruction(instr);
   return instr;
@@ -1472,26 +1617,46 @@ inline HSimulate* HGraphBuilder::Add(BailoutId id,
 
 
 template<>
-inline HSimulate* HGraphBuilder::Add(BailoutId id) {
-  return Add<HSimulate>(id, FIXED_SIMULATE);
+inline HInstruction* HGraphBuilder::NewUncasted<HLoadNamedField>(
+    HValue* object, HObjectAccess access) {
+  return NewUncasted<HLoadNamedField>(object, access,
+                                      static_cast<HValue*>(NULL));
 }
 
 
 template<>
-inline HReturn* HGraphBuilder::Add(HValue* value) {
-  HValue* context = environment()->LookupContext();
+inline HInstruction* HGraphBuilder::AddUncasted<HLoadNamedField>(
+    HValue* object, HObjectAccess access) {
+  return AddUncasted<HLoadNamedField>(object, access,
+                                      static_cast<HValue*>(NULL));
+}
+
+
+template<>
+inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
+  return AddUncasted<HSimulate>(id, FIXED_SIMULATE);
+}
+
+
+template<>
+inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
   int num_parameters = graph()->info()->num_parameters();
-  HValue* params = Add<HConstant>(num_parameters);
-  HReturn* return_instruction = new(graph()->zone())
-      HReturn(value, context, params);
+  HValue* params = AddUncasted<HConstant>(num_parameters);
+  HReturn* return_instruction = New<HReturn>(value, params);
   current_block()->FinishExit(return_instruction);
   return return_instruction;
 }
 
 
 template<>
-inline HReturn* HGraphBuilder::Add(HConstant* p1) {
-  return Add<HReturn>(static_cast<HValue*>(p1));
+inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
+  return AddUncasted<HReturn>(static_cast<HValue*>(value));
+}
+
+
+template<>
+inline HInstruction* HGraphBuilder::NewUncasted<HContext>() {
+  return HContext::New(zone());
 }
 
 
@@ -1560,7 +1725,9 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
 
   bool inline_bailout() { return inline_bailout_; }
 
-  void Bailout(const char* reason);
+  HValue* context() { return environment()->context(); }
+
+  void Bailout(BailoutReason reason);
 
   HBasicBlock* CreateJoin(HBasicBlock* first,
                           HBasicBlock* second,
@@ -1641,8 +1808,6 @@ 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);
@@ -1835,8 +2000,7 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
                                Expression* sub_expr,
                                NilValue nil);
 
-  HInstruction* BuildStringCharCodeAt(HValue* context,
-                                      HValue* string,
+  HInstruction* BuildStringCharCodeAt(HValue* string,
                                       HValue* index);
   HInstruction* BuildBinaryOperation(BinaryOperation* expr,
                                      HValue* left,
@@ -1892,9 +2056,6 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
 
   void AddCheckMap(HValue* object, Handle<Map> map);
 
-  void AddCheckMapsWithTransitions(HValue* object,
-                                   Handle<Map> map);
-
   void BuildStoreNamed(Expression* expression,
                        BailoutId id,
                        int position,
diff --git a/deps/v8/src/i18n.cc b/deps/v8/src/i18n.cc
new file mode 100644 (file)
index 0000000..b2ccfd4
--- /dev/null
@@ -0,0 +1,297 @@
+// 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/dtfmtsym.h"
+#include "unicode/dtptngen.h"
+#include "unicode/locid.h"
+#include "unicode/numsys.h"
+#include "unicode/smpdtfmt.h"
+#include "unicode/timezone.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+icu::SimpleDateFormat* CreateICUDateFormat(
+    Isolate* isolate,
+    const icu::Locale& icu_locale,
+    Handle<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;
+  MaybeObject* maybe_object = options->GetProperty(
+      *isolate->factory()->NewStringFromAscii(CStrVector("timeZone")));
+  Object* timezone;
+  if (maybe_object->ToObject(&timezone) && timezone->IsString()) {
+    v8::String::Utf8Value utf8_timezone(
+        v8::Utils::ToLocal(Handle<String>(String::cast(timezone))));
+    icu::UnicodeString u_timezone(icu::UnicodeString::fromUTF8(*utf8_timezone));
+    tz = icu::TimeZone::createTimeZone(u_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;
+  Object* skeleton;
+  maybe_object = options->GetProperty(
+      *isolate->factory()->NewStringFromAscii(CStrVector("skeleton")));
+  if (maybe_object->ToObject(&skeleton) && skeleton->IsString()) {
+    v8::String::Utf8Value utf8_skeleton(
+        v8::Utils::ToLocal(Handle<String>(String::cast(skeleton))));
+    icu::UnicodeString u_skeleton(icu::UnicodeString::fromUTF8(*utf8_skeleton));
+    icu::DateTimePatternGenerator* generator =
+        icu::DateTimePatternGenerator::createInstance(icu_locale, status);
+    icu::UnicodeString pattern;
+    if (U_SUCCESS(status)) {
+      pattern = generator->getBestPattern(u_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 SetResolvedSettings(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));
+}
+
+}  // 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).
+    SetResolvedSettings(isolate, no_extension_locale, date_format, resolved);
+  } else {
+    SetResolvedSettings(isolate, icu_locale, date_format, resolved);
+  }
+
+  return date_format;
+}
+
+
+icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
+    Isolate* isolate,
+    Handle<JSObject> obj) {
+  if (obj->HasLocalProperty(
+          *isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")))) {
+    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);
+}
+
+} }  // namespace v8::internal
similarity index 69%
rename from deps/v8/src/extensions/i18n/date-format.h
rename to deps/v8/src/i18n.h
index daa5964..37c57b1 100644 (file)
@@ -26,8 +26,8 @@
 // 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_
+#ifndef V8_I18N_H_
+#define V8_I18N_H_
 
 #include "unicode/uversion.h"
 #include "v8.h"
@@ -36,36 +36,44 @@ namespace U_ICU_NAMESPACE {
 class SimpleDateFormat;
 }
 
-namespace v8_i18n {
+namespace v8 {
+namespace internal {
 
-class DateFormat {
+class I18N {
  public:
-  static void JSCreateDateTimeFormat(
-      const v8::FunctionCallbackInfo<v8::Value>& args);
+  // 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();
+};
 
-  // Helper methods for various bindings.
+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(
-      v8::Handle<v8::Object> obj);
+  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,
-                               v8::Persistent<v8::Object>* object,
+                               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
+} }  // namespace v8::internal
 
-#endif  // V8_EXTENSIONS_I18N_DATE_FORMAT_H_
+#endif  // V8_I18N_H_
index e0ae006..7bea373 100644 (file)
@@ -1227,6 +1227,10 @@ 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);
index b90a17f..59124ea 100644 (file)
@@ -241,7 +241,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         if (FLAG_debug_code) {
           __ cmp(esi, edi);
           __ Assert(less_equal,
-                    "Unexpected number of pre-allocated property fields.");
+                    kUnexpectedNumberOfPreAllocatedPropertyFields);
         }
         __ 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, "Property allocation count failed.");
+      __ Assert(positive, kPropertyAllocationCountFailed);
 
       // 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("no cases left");
+  __ Abort(kNoCasesLeft);
 }
 
 
@@ -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, "Unexpected initial map for InternalArray function");
+    __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
     __ CmpObjectType(ebx, MAP_TYPE, ecx);
-    __ Assert(equal, "Unexpected initial map for InternalArray function");
+    __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
   }
 
   // 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, "Unexpected initial map for Array function");
+    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
     __ CmpObjectType(ebx, MAP_TYPE, ecx);
-    __ Assert(equal, "Unexpected initial map for Array function");
+    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
   }
 
   // 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, "Unexpected String function");
+    __ Assert(equal, kUnexpectedStringFunction);
   }
 
   // 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, "Unexpected string wrapper instance size");
+    __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
     __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0);
-    __ Assert(equal, "Unexpected unused properties of string wrapper");
+    __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
   }
   __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
 
index 5789f49..8721656 100644 (file)
@@ -250,17 +250,6 @@ 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) {
@@ -511,9 +500,8 @@ 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, message);
+    __ Assert(equal, kExpected0AsASmiSentinel);
   }
   __ mov(ecx, GlobalObjectOperand());
   __ mov(ecx, FieldOperand(ecx, GlobalObject::kNativeContextOffset));
@@ -3469,9 +3457,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
   if (FLAG_debug_code) {
     __ test(ecx, Immediate(kSmiTagMask));
-    __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected");
+    __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected);
     __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
-    __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
+    __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
   }
 
   // ecx: RegExp data (FixedArray)
@@ -3831,7 +3819,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, "external string expected, but not found");
+    __ Assert(zero, kExternalStringExpectedButNotFound);
   }
   __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
   // Move the pointer so that offset-wise, it looks like a sequential string.
@@ -4326,7 +4314,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
                                                        edi);
   }
 #ifdef DEBUG
-  __ Abort("Unexpected fall-through from string comparison");
+  __ Abort(kUnexpectedFallThroughFromStringComparison);
 #endif
 
   __ bind(&check_unequal_objects);
@@ -5085,9 +5073,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     __ sub(scratch, Operand(esp, 1 * kPointerSize));
     if (FLAG_debug_code) {
       __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1);
       __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp2);
     }
     __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate));
     __ mov(Operand(scratch, 0), map);
@@ -5120,7 +5108,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     __ sub(scratch, Operand(esp, 1 * kPointerSize));
     if (FLAG_debug_code) {
       __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
     }
     __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
     if (!ReturnTrueFalseObject()) {
@@ -5142,7 +5130,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     __ sub(scratch, Operand(esp, 1 * kPointerSize));
     if (FLAG_debug_code) {
       __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
     }
     __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
     if (!ReturnTrueFalseObject()) {
@@ -5255,7 +5243,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharCodeAtGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
 
   // Index is not a smi.
   __ bind(&index_not_smi_);
@@ -5305,7 +5293,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
 }
 
 
@@ -5340,7 +5328,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharFromCodeGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
 
   __ bind(&slow_case_);
   call_helper.BeforeCall(masm);
@@ -5352,7 +5340,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
 }
 
 
@@ -7482,7 +7470,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -7545,7 +7533,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -7610,9 +7598,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, "Unexpected initial map for Array function");
+    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
     __ CmpObjectType(ecx, MAP_TYPE, ecx);
-    __ Assert(equal, "Unexpected initial map for Array function");
+    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
 
     // We should either have undefined in ebx or a valid cell
     Label okay_here;
@@ -7620,7 +7608,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ cmp(ebx, Immediate(undefined_sentinel));
     __ j(equal, &okay_here);
     __ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
-    __ Assert(equal, "Expected property cell in register ebx");
+    __ Assert(equal, kExpectedPropertyCellInRegisterEbx);
     __ bind(&okay_here);
   }
 
@@ -7724,9 +7712,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, "Unexpected initial map for Array function");
+    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
     __ CmpObjectType(ecx, MAP_TYPE, ecx);
-    __ Assert(equal, "Unexpected initial map for Array function");
+    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
   }
 
   // Figure out the right elements kind
@@ -7745,7 +7733,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ j(equal, &done);
     __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS));
     __ Assert(equal,
-              "Invalid ElementsKind for InternalArray or InternalPackedArray");
+              kInvalidElementsKindForInternalArrayOrInternalPackedArray);
     __ bind(&done);
   }
 
index f488718..28b0f4a 100644 (file)
@@ -779,7 +779,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
 
   if (FLAG_debug_code) {
     __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
-    __ Assert(equal, "object found in smi-only array");
+    __ Assert(equal, kObjectFoundInSmiOnlyArray);
   }
 
   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, "external string expected, but not found");
+    __ Assert(zero, kExternalStringExpectedButNotFound);
   }
   // Rule out short external strings.
   STATIC_CHECK(kShortExternalStringTag != 0);
index 68199f9..fd703dc 100644 (file)
@@ -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, "Unable to encode value as smi");
+          __ Assert(zero, kUnableToEncodeValueAsSmi);
         }
         __ SmiTag(reg);
         __ push(reg);
index 4896806..a9bd8c5 100644 (file)
@@ -625,7 +625,7 @@ void Deoptimizer::EntryGenerator::Generate() {
     __ pop(ecx);
     if (FLAG_debug_code) {
       __ cmp(ecx, Immediate(kAlignmentZapValue));
-      __ Assert(equal, "alignment marker expected");
+      __ Assert(equal, kAlignmentMarkerExpected);
     }
     __ bind(&no_padding);
   } else {
index 6223748..8606125 100644 (file)
@@ -136,6 +136,11 @@ inline Object* JavaScriptFrame::function_slot_object() const {
 }
 
 
+inline void StackHandler::SetFp(Address slot, Address fp) {
+  Memory::Address_at(slot) = fp;
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_IA32_FRAMES_IA32_H_
index 8f11acc..f08a269 100644 (file)
@@ -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, "Declaration in with context.");
+    __ Check(not_equal, kDeclarationInWithContext);
     __ cmp(ebx, isolate()->factory()->catch_context_map());
-    __ Check(not_equal, "Declaration in catch context.");
+    __ Check(not_equal, kDeclarationInCatchContext);
   }
 }
 
@@ -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("Generator failed to resume.");
+  __ Abort(kGeneratorFailedToResume);
 
   // 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, "Let binding re-initialization.");
+        __ Check(equal, kLetBindingReInitialization);
       }
       // 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, "Non-smi index");
+  __ Check(zero, kNonSmiIndex);
   __ test(value, Immediate(kSmiTagMask));
-  __ Check(zero, "Non-smi value");
+  __ Check(zero, kNonSmiValue);
 
   __ cmp(index, FieldOperand(string, String::kLengthOffset));
-  __ Check(less, "Index is too large");
+  __ Check(less, kIndexIsTooLarge);
 
   __ cmp(index, Immediate(Smi::FromInt(0)));
-  __ Check(greater_equal, "Index is negative");
+  __ Check(greater_equal, kIndexIsNegative);
 
   __ 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, "Unexpected string type");
+  __ Check(equal, kUnexpectedStringType);
   __ 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("Attempt to use undefined cache.");
+    __ Abort(kAttemptToUseUndefinedCache);
     __ 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, "No empty arrays here in EmitFastAsciiArrayJoin");
+    __ Assert(less, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
   }
   __ bind(&loop);
   __ mov(string, FieldOperand(elements,
@@ -4347,34 +4347,12 @@ 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());
index bf0c80b..1e0f14e 100644 (file)
@@ -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, "Map is no longer in eax.");
+    __ Check(equal, kMapIsNoLongerInEax);
   }
   __ mov(ebx, eax);  // Keep the map around for later.
   __ shr(eax, KeyedLookupCache::kMapHashShift);
index 3ddad06..061ec9b 100644 (file)
@@ -113,7 +113,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
 }
 
 
-void LCodeGen::Abort(const char* reason) {
+void LCodeGen::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -137,6 +137,16 @@ void LCodeGen::Comment(const char* format, ...) {
 }
 
 
+#ifdef _MSC_VER
+void LCodeGen::MakeSureStackPagesMapped(int offset) {
+  const int kPageSize = 4 * KB;
+  for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
+    __ mov(Operand(esp, offset), eax);
+  }
+}
+#endif
+
+
 bool LCodeGen::GeneratePrologue() {
   ASSERT(is_generating());
 
@@ -210,7 +220,7 @@ bool LCodeGen::GeneratePrologue() {
       dynamic_frame_alignment_ &&
       FLAG_debug_code) {
     __ test(esp, Immediate(kPointerSize));
-    __ Assert(zero, "frame is expected to be aligned");
+    __ Assert(zero, kFrameIsExpectedToBeAligned);
   }
 
   // Reserve space for the stack slots needed by the code.
@@ -226,6 +236,9 @@ bool LCodeGen::GeneratePrologue() {
     } else {
       if (FLAG_debug_code) {
         __ sub(Operand(esp), Immediate(slots * kPointerSize));
+#ifdef _MSC_VER
+        MakeSureStackPagesMapped(slots * kPointerSize);
+#endif
         __ push(eax);
         __ mov(Operand(eax), Immediate(slots));
         Label loop;
@@ -238,15 +251,7 @@ bool LCodeGen::GeneratePrologue() {
       } else {
         __ sub(Operand(esp), Immediate(slots * kPointerSize));
 #ifdef _MSC_VER
-        // On windows, you may not access the stack more than one page below
-        // the most recently mapped page. To make the allocated area randomly
-        // accessible, we write to each page in turn (the value is irrelevant).
-        const int kPageSize = 4 * KB;
-        for (int offset = slots * kPointerSize - kPageSize;
-             offset > 0;
-             offset -= kPageSize) {
-          __ mov(Operand(esp, offset), eax);
-        }
+        MakeSureStackPagesMapped(slots * kPointerSize);
 #endif
       }
 
@@ -877,7 +882,7 @@ void LCodeGen::LoadContextFromDeferred(LOperand* context) {
   } else if (context->IsConstantOperand()) {
     HConstant* constant =
         chunk_->LookupConstant(LConstantOperand::cast(context));
-    __ LoadHeapObject(esi, Handle<Context>::cast(constant->handle()));
+    __ LoadObject(esi, Handle<Object>::cast(constant->handle()));
   } else {
     UNREACHABLE();
   }
@@ -943,7 +948,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
   Address entry =
       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
   if (entry == NULL) {
-    Abort("bailout was not prepared");
+    Abort(kBailoutWasNotPrepared);
     return;
   }
 
@@ -1674,8 +1679,9 @@ void LCodeGen::DoBitI(LBitI* instr) {
   ASSERT(left->IsRegister());
 
   if (right->IsConstantOperand()) {
-    int right_operand = ToRepresentation(LConstantOperand::cast(right),
-                                         instr->hydrogen()->representation());
+    int32_t right_operand =
+        ToRepresentation(LConstantOperand::cast(right),
+                         instr->hydrogen()->representation());
     switch (instr->op()) {
       case Token::BIT_AND:
         __ and_(ToRegister(left), right_operand);
@@ -1684,7 +1690,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
         __ or_(ToRegister(left), right_operand);
         break;
       case Token::BIT_XOR:
-        __ xor_(ToRegister(left), right_operand);
+        if (right_operand == int32_t(~0)) {
+          __ not_(ToRegister(left));
+        } else {
+          __ xor_(ToRegister(left), right_operand);
+        }
         break;
       default:
         UNREACHABLE();
@@ -1771,7 +1781,9 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
         if (shift_count != 0) {
           if (instr->hydrogen_value()->representation().IsSmi() &&
               instr->can_deopt()) {
-            __ shl(ToRegister(left), shift_count - 1);
+            if (shift_count != 1) {
+              __ shl(ToRegister(left), shift_count - 1);
+            }
             __ SmiTag(ToRegister(left));
             DeoptimizeIf(overflow, instr->environment());
           } else {
@@ -1969,7 +1981,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, "Unexpected string type");
+    __ Check(equal, kUnexpectedStringType);
     __ pop(value);
   }
 
@@ -1983,13 +1995,6 @@ 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));
@@ -2856,7 +2861,7 @@ void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
       __ cmp(Operand(esp,
                      (parameter_count + extra_value_count) * kPointerSize),
              Immediate(kAlignmentZapValue));
-      __ Assert(equal, "expected alignment marker");
+      __ Assert(equal, kExpectedAlignmentMarker);
     }
     __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
   } else {
@@ -2869,7 +2874,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, "expected alignment marker");
+      __ Assert(equal, kExpectedAlignmentMarker);
     }
 
     // emit code to restore stack based on instr->parameter_count()
@@ -2989,20 +2994,6 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
 }
 
 
-void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) {
-  Register object = ToRegister(instr->object());
-  Register temp = ToRegister(instr->temp());
-  ExternalReference sites_list_address = instr->GetReference(isolate());
-
-  __ mov(temp, Immediate(sites_list_address));
-  __ mov(temp, Operand(temp, 0));
-  __ mov(FieldOperand(object, instr->hydrogen()->store_field().offset()),
-         temp);
-  __ mov(temp, Immediate(sites_list_address));
-  __ mov(Operand(temp, 0), object);
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -3163,9 +3154,6 @@ static bool CompactEmit(SmallMapList* list,
                         int i,
                         Isolate* isolate) {
   Handle<Map> map = list->at(i);
-  // If the map has ElementsKind transitions, we will generate map checks
-  // for each kind in __ CompareMap(..., ALLOW_ELEMENTS_TRANSITION_MAPS).
-  if (map->HasElementsTransition()) return false;
   LookupResult lookup(isolate);
   map->LookupDescriptor(NULL, *name, &lookup);
   return lookup.IsField() || lookup.IsConstant();
@@ -3457,7 +3445,7 @@ Operand LCodeGen::BuildFastArrayOperand(
   if (key->IsConstantOperand()) {
     int constant_value = ToInteger32(LConstantOperand::cast(key));
     if (constant_value & 0xF0000000) {
-      Abort("array index constant value too big");
+      Abort(kArrayIndexConstantValueTooBig);
     }
     return Operand(elements_pointer_reg,
                    ((constant_value + additional_index) << shift_size)
@@ -3831,7 +3819,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
     __ xorps(scratch, scratch);
     __ subsd(scratch, input_reg);
     __ pand(input_reg, scratch);
-  } else if (r.IsInteger32()) {
+  } else if (r.IsSmiOrInteger32()) {
     EmitIntegerMathAbs(instr);
   } else {  // Tagged case.
     DeferredMathAbsTaggedHeapNumber* deferred =
@@ -4357,6 +4345,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   int offset = access.offset();
 
   if (access.IsExternalMemory()) {
+    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
     MemOperand operand = instr->object()->IsConstantOperand()
         ? MemOperand::StaticVariable(
             ToExternalReference(LConstantOperand::cast(instr->object())))
@@ -4876,13 +4865,6 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
 }
 
 
-void LCodeGen::DoStringLength(LStringLength* instr) {
-  Register string = ToRegister(instr->string());
-  Register result = ToRegister(instr->result());
-  __ mov(result, FieldOperand(string, String::kLengthOffset));
-}
-
-
 void LCodeGen::DoStringAdd(LStringAdd* instr) {
   EmitPushTaggedOperand(instr->left());
   EmitPushTaggedOperand(instr->right());
@@ -5809,31 +5791,68 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
 }
 
 
-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::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::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);
 
-  Label success;
   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;
   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();
-  DoCheckMapCommon(reg, map, instr);
+  __ CompareMap(reg, map, &success);
+  if (instr->hydrogen()->has_migration_target()) {
+    __ j(not_equal, deferred->entry());
+  } else {
+    DeoptimizeIf(not_equal, instr->environment());
+  }
+
   __ bind(&success);
 }
 
@@ -6010,22 +6029,6 @@ 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:
@@ -6048,10 +6051,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
   }
 
@@ -6103,11 +6108,13 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
     __ push(Immediate(Smi::FromInt(size)));
   }
 
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(
         Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context());
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(
         Runtime::kAllocateInOldDataSpace, 1, instr, instr->context());
   } else {
index 27295da..c9a7899 100644 (file)
@@ -163,8 +163,7 @@ class LCodeGen BASE_EMBEDDED {
   void DoDeferredAllocate(LAllocate* instr);
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
-
-  void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
+  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
@@ -212,7 +211,7 @@ class LCodeGen BASE_EMBEDDED {
 
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
   void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
@@ -295,7 +294,7 @@ class LCodeGen BASE_EMBEDDED {
   Register ToRegister(int index) const;
   XMMRegister ToDoubleRegister(int index) const;
   X87Register ToX87Register(int index) const;
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   ExternalReference ToExternalReference(LConstantOperand* op) const;
 
@@ -408,6 +407,14 @@ class LCodeGen BASE_EMBEDDED {
   int X87ArrayIndex(X87Register reg);
   int x87_st2idx(int pos);
 
+#ifdef _MSC_VER
+  // On windows, you may not access the stack more than one page below
+  // the most recently mapped page. To make the allocated area randomly
+  // accessible, we write an arbitrary value to each page in range
+  // esp + offset - page_size .. esp in turn.
+  void MakeSureStackPagesMapped(int offset);
+#endif
+
   Zone* zone_;
   LPlatformChunk* const chunk_;
   MacroAssembler* const masm_;
index 8c8103f..52f39d4 100644 (file)
@@ -302,24 +302,6 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) {
 }
 
 
-ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) {
-  switch (hydrogen()->known_list()) {
-    case HLinkObjectInList::ALLOCATION_SITE_LIST:
-      return ExternalReference::allocation_sites_list_address(isolate);
-  }
-
-  UNREACHABLE();
-  // Return a dummy value
-  return ExternalReference::isolate_address(isolate);
-}
-
-
-void LLinkObjectInList::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add(" offset %d", hydrogen()->store_field().offset());
-}
-
-
 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
   context()->PrintTo(stream);
   stream->Add("[%d]", slot_index());
@@ -505,7 +487,7 @@ LPlatformChunk* LChunkBuilder::Build() {
 }
 
 
-void LChunkBuilder::Abort(const char* reason) {
+void LChunkBuilder::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -716,7 +698,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
   int vreg = allocator_->GetVirtualRegister();
   if (!allocator_->AllocationOk()) {
-    Abort("Out of virtual registers while trying to allocate temp register.");
+    Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
     vreg = 0;
   }
   operand->set_virtual_register(vreg);
@@ -1432,16 +1414,6 @@ 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);
@@ -1869,17 +1841,6 @@ 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()),
@@ -2067,15 +2028,6 @@ 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
@@ -2089,10 +2041,16 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
 
 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
   LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
+  if (!instr->CanOmitMapChecks()) {
+    value = UseRegisterAtStart(instr->value());
+    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
+  }
   LCheckMaps* result = new(zone()) LCheckMaps(value);
-  if (instr->CanOmitMapChecks()) return result;
-  return AssignEnvironment(result);
+  if (!instr->CanOmitMapChecks()) {
+    AssignEnvironment(result);
+    if (instr->has_migration_target()) return AssignPointerMap(result);
+  }
+  return result;
 }
 
 
@@ -2191,14 +2149,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) {
-  LOperand* object = UseRegister(instr->value());
-  LOperand* temp = TempRegister();
-  LLinkObjectInList* result = new(zone()) LLinkObjectInList(object, temp);
-  return result;
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
@@ -2444,7 +2394,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->transition().is_null() &&
+  bool needs_write_barrier_for_map = instr->has_transition() &&
       instr->NeedsWriteBarrierForMap();
 
   LOperand* obj;
@@ -2540,12 +2490,6 @@ LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
-  LOperand* string = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   info()->MarkAsDeferredCalling();
   LOperand* context = UseAny(instr->context());
@@ -2599,7 +2543,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("Too many spill slots needed for OSR");
+    Abort(kTooManySpillSlotsNeededForOSR);
     spill_index = 0;
   }
   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
index 6a2aa00..effecb7 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -68,7 +67,6 @@ class LCodeGen;
   V(CheckMaps)                                  \
   V(CheckMapValue)                              \
   V(CheckNonSmi)                                \
-  V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
@@ -120,7 +118,6 @@ class LCodeGen;
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
   V(LazyBailout)                                \
-  V(LinkObjectInList)                           \
   V(LoadContextSlot)                            \
   V(LoadExternalArrayPointer)                   \
   V(LoadFieldByIndex)                           \
@@ -175,7 +172,6 @@ class LCodeGen;
   V(StringCharCodeAt)                           \
   V(StringCharFromCode)                         \
   V(StringCompareAndBranch)                     \
-  V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
   V(TaggedToINoSSE2)                            \
@@ -1360,18 +1356,6 @@ 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) {
@@ -1705,25 +1689,6 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 3, 0> {
 };
 
 
-class LLinkObjectInList: public LTemplateInstruction<0, 1, 1> {
- public:
-  explicit LLinkObjectInList(LOperand* object, LOperand* temp) {
-    inputs_[0] = object;
-    temps_[0] = temp;
-  }
-
-  LOperand* object() { return inputs_[0]; }
-  LOperand* temp() { return temps_[0]; }
-
-  ExternalReference GetReference(Isolate* isolate);
-
-  DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list")
-  DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList)
-
-  virtual void PrintDataTo(StringStream* stream);
-};
-
-
 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
@@ -2257,7 +2222,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 2> {
 
   virtual void PrintDataTo(StringStream* stream);
 
-  Handle<Map> transition() const { return hydrogen()->transition(); }
+  Handle<Map> transition() const { return hydrogen()->transition_map(); }
   Representation representation() const {
     return hydrogen()->field_representation();
   }
@@ -2431,19 +2396,6 @@ class LStringCharFromCode: public LTemplateInstruction<1, 2, 0> {
 };
 
 
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LStringLength(LOperand* string) {
-    inputs_[0] = string;
-  }
-
-  LOperand* string() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
-  DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
 class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckFunction(LOperand* value) {
@@ -2485,24 +2437,6 @@ 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) {
@@ -2834,7 +2768,7 @@ class LChunkBuilder BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
 
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
index 6d1cb16..8b1be3c 100644 (file)
@@ -678,7 +678,7 @@ void MacroAssembler::AssertNumber(Register object) {
     JumpIfSmi(object, &ok);
     cmp(FieldOperand(object, HeapObject::kMapOffset),
         isolate()->factory()->heap_number_map());
-    Check(equal, "Operand not a number");
+    Check(equal, kOperandNotANumber);
     bind(&ok);
   }
 }
@@ -687,7 +687,7 @@ void MacroAssembler::AssertNumber(Register object) {
 void MacroAssembler::AssertSmi(Register object) {
   if (emit_debug_code()) {
     test(object, Immediate(kSmiTagMask));
-    Check(equal, "Operand is not a smi");
+    Check(equal, kOperandIsNotASmi);
   }
 }
 
@@ -695,12 +695,12 @@ void MacroAssembler::AssertSmi(Register object) {
 void MacroAssembler::AssertString(Register object) {
   if (emit_debug_code()) {
     test(object, Immediate(kSmiTagMask));
-    Check(not_equal, "Operand is a smi and not a string");
+    Check(not_equal, kOperandIsASmiAndNotAString);
     push(object);
     mov(object, FieldOperand(object, HeapObject::kMapOffset));
     CmpInstanceType(object, FIRST_NONSTRING_TYPE);
     pop(object);
-    Check(below, "Operand is not a string");
+    Check(below, kOperandIsNotAString);
   }
 }
 
@@ -708,12 +708,12 @@ void MacroAssembler::AssertString(Register object) {
 void MacroAssembler::AssertName(Register object) {
   if (emit_debug_code()) {
     test(object, Immediate(kSmiTagMask));
-    Check(not_equal, "Operand is a smi and not a name");
+    Check(not_equal, kOperandIsASmiAndNotAName);
     push(object);
     mov(object, FieldOperand(object, HeapObject::kMapOffset));
     CmpInstanceType(object, LAST_NAME_TYPE);
     pop(object);
-    Check(below_equal, "Operand is not a name");
+    Check(below_equal, kOperandIsNotAName);
   }
 }
 
@@ -721,7 +721,7 @@ void MacroAssembler::AssertName(Register object) {
 void MacroAssembler::AssertNotSmi(Register object) {
   if (emit_debug_code()) {
     test(object, Immediate(kSmiTagMask));
-    Check(not_equal, "Operand is a smi");
+    Check(not_equal, kOperandIsASmi);
   }
 }
 
@@ -734,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, "code object not properly patched");
+    Check(not_equal, kCodeObjectNotProperlyPatched);
   }
 }
 
@@ -743,7 +743,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
   if (emit_debug_code()) {
     cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
         Immediate(Smi::FromInt(type)));
-    Check(equal, "stack frame types must match");
+    Check(equal, kStackFrameTypesMustMatch);
   }
   leave();
 }
@@ -1024,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, "we should not have an empty lexical context");
+    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
   }
   // Load the native context of the current context.
   int offset =
@@ -1037,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, "JSGlobalObject::native_context should be a native context.");
+    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   }
 
   // Check if both contexts are the same.
@@ -1056,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, "JSGlobalProxy::context() should not be null.");
+    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
 
     // Read the first word and compare to native_context_map(),
     cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
         isolate()->factory()->native_context_map());
-    Check(equal, "JSGlobalObject::native_context should be a native context.");
+    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   }
 
   int token_offset = Context::kHeaderSize +
@@ -1206,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, "Unexpected allocation top");
+    Check(equal, kUnexpectedAllocationTop);
 #endif
     return;
   }
@@ -1226,7 +1226,7 @@ void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
                                                AllocationFlags flags) {
   if (emit_debug_code()) {
     test(result_end, Immediate(kObjectAlignmentMask));
-    Check(zero, "Unaligned allocation in new space");
+    Check(zero, kUnalignedAllocationInNewSpace);
   }
 
   ExternalReference allocation_top =
@@ -1458,7 +1458,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object) {
   and_(object, Immediate(~kHeapObjectTagMask));
 #ifdef DEBUG
   cmp(object, Operand::StaticVariable(new_space_allocation_top));
-  Check(below, "Undo allocation of non allocated memory");
+  Check(below, kUndoAllocationOfNonAllocatedMemory);
 #endif
   mov(Operand::StaticVariable(new_space_allocation_top), object);
 }
@@ -1933,7 +1933,7 @@ void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
 // If false, it is returned as a pointer to a preallocated by caller memory
 // region. Pointer to this region should be passed to a function as an
 // implicit first argument.
-#if V8_OS_BSD4 || V8_OS_MINGW32 || V8_OS_CYGWIN
+#if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__)
 static const bool kReturnHandlesDirectly = true;
 #else
 static const bool kReturnHandlesDirectly = false;
@@ -2062,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, "Invalid HandleScope level");
+  Assert(above_equal, kInvalidHandleScopeLevel);
   cmp(edi, Operand::StaticVariable(limit_address));
   j(not_equal, &delete_allocated_handles);
   bind(&leave_exit_frame);
@@ -2104,7 +2104,7 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
   cmp(return_value, isolate()->factory()->null_value());
   j(equal, &ok, Label::kNear);
 
-  Abort("API call returned invalid object");
+  Abort(kAPICallReturnedInvalidObject);
 
   bind(&ok);
 #endif
@@ -2390,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, "Variable resolved to with context.");
+    Check(not_equal, kVariableResolvedToWithContext);
   }
 }
 
@@ -2477,7 +2477,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
     CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
     jmp(&ok);
     bind(&fail);
-    Abort("Global functions must have initial map");
+    Abort(kGlobalFunctionsMustHaveInitialMap);
     bind(&ok);
   }
 }
@@ -2578,7 +2578,7 @@ void MacroAssembler::VerifyX87StackDepth(uint32_t depth) {
   and_(eax, kTopMask);
   shr(eax, 11);
   cmp(eax, Immediate(tos));
-  Check(equal, "Unexpected FPU stack depth after instruction");
+  Check(equal, kUnexpectedFPUStackDepthAfterInstruction);
   fnclex();
   pop(eax);
 }
@@ -2661,8 +2661,8 @@ void MacroAssembler::DecrementCounter(Condition cc,
 }
 
 
-void MacroAssembler::Assert(Condition cc, const char* msg) {
-  if (emit_debug_code()) Check(cc, msg);
+void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
+  if (emit_debug_code()) Check(cc, reason);
 }
 
 
@@ -2679,16 +2679,16 @@ void MacroAssembler::AssertFastElements(Register elements) {
     cmp(FieldOperand(elements, HeapObject::kMapOffset),
         Immediate(factory->fixed_cow_array_map()));
     j(equal, &ok);
-    Abort("JSObject with fast elements map has slow elements");
+    Abort(kJSObjectWithFastElementsMapHasSlowElements);
     bind(&ok);
   }
 }
 
 
-void MacroAssembler::Check(Condition cc, const char* msg) {
+void MacroAssembler::Check(Condition cc, BailoutReason reason) {
   Label L;
   j(cc, &L);
-  Abort(msg);
+  Abort(reason);
   // will not return here
   bind(&L);
 }
@@ -2709,12 +2709,13 @@ void MacroAssembler::CheckStackAlignment() {
 }
 
 
-void MacroAssembler::Abort(const char* msg) {
+void MacroAssembler::Abort(BailoutReason reason) {
   // 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());
@@ -3118,7 +3119,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, "Live Bytes Count overflow chunk size");
+    Check(less_equal, kLiveBytesCountOverflowChunkSize);
   }
 
   bind(&done);
index 3bca930..165c9ce 100644 (file)
@@ -807,6 +807,8 @@ 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() {
@@ -844,15 +846,15 @@ class MacroAssembler: public Assembler {
 
   // Calls Abort(msg) if the condition cc is not satisfied.
   // Use --debug_code to enable.
-  void Assert(Condition cc, const char* msg);
+  void Assert(Condition cc, BailoutReason reason);
 
   void AssertFastElements(Register elements);
 
   // Like Assert(), but always enabled.
-  void Check(Condition cc, const char* msg);
+  void Check(Condition cc, BailoutReason reason);
 
   // Print a message to stdout and abort execution.
-  void Abort(const char* msg);
+  void Abort(BailoutReason reason);
 
   // Check that the stack is aligned.
   void CheckStackAlignment();
index 123506f..b7828b8 100644 (file)
@@ -3153,7 +3153,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
     __ j(equal, &miss);
   } else if (FLAG_debug_code) {
     __ cmp(eax, factory()->the_hole_value());
-    __ Check(not_equal, "DontDelete cells can't contain the hole");
+    __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
   }
 
   HandlerFrontendFooter(name, &success, &miss);
index 269754b..3c22580 100644 (file)
@@ -233,16 +233,22 @@ static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
 
   // The stub is not in the cache. We've ruled out all other kinds of failure
   // except for proptotype chain changes, a deprecated map, a map that's
-  // different from the one that the stub expects, or a constant global property
-  // that will become mutable. Threat all those situations as prototype failures
-  // (stay monomorphic if possible).
+  // different from the one that the stub expects, elements kind changes, or a
+  // constant global property that will become mutable. Threat all those
+  // situations as prototype failures (stay monomorphic if possible).
 
   // If the IC is shared between multiple receivers (slow dictionary mode), then
   // the map cannot be deprecated and the stub invalidated.
   if (cache_holder == OWN_MAP) {
     Map* old_map = target->FindFirstMap();
     if (old_map == map) return true;
-    if (old_map != NULL && old_map->is_deprecated()) return true;
+    if (old_map != NULL) {
+      if (old_map->is_deprecated()) return true;
+      if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
+                                              map->elements_kind())) {
+        return true;
+      }
+    }
   }
 
   if (receiver->IsGlobalObject()) {
@@ -384,7 +390,6 @@ 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
@@ -2583,27 +2588,6 @@ 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);
index 7820d40..fcf0de5 100644 (file)
@@ -714,14 +714,6 @@ 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:
index 91f4527..b9bd65e 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "icu_util.h"
 
-#if defined(_WIN32) && defined(ENABLE_I18N_SUPPORT)
+#if defined(_WIN32) && defined(V8_I18N_SUPPORT)
 #include <windows.h>
 
 #include "unicode/putil.h"
@@ -42,7 +42,7 @@ namespace v8 {
 namespace internal {
 
 bool InitializeICU() {
-#if defined(_WIN32) && defined(ENABLE_I18N_SUPPORT)
+#if defined(_WIN32) && defined(V8_I18N_SUPPORT)
   // We expect to find the ICU data module alongside the current module.
   HMODULE module = LoadLibraryA(ICU_UTIL_DATA_SHARED_MODULE_NAME);
   if (!module) return false;
index 61f1e2d..448c719 100644 (file)
@@ -1774,6 +1774,7 @@ 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),
@@ -2052,6 +2053,8 @@ 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;
@@ -2183,6 +2186,7 @@ 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);
index c008317..74bfc29 100644 (file)
@@ -922,6 +922,8 @@ 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_; }
@@ -1295,6 +1297,7 @@ 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_;
index e9c3531..790a218 100644 (file)
@@ -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("not enough virtual registers for values");
+    info->set_bailout_reason(kNotEnoughVirtualRegistersForValues);
     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("not enough virtual registers (regalloc)");
+    info->set_bailout_reason(kNotEnoughVirtualRegistersRegalloc);
     return NULL;
   }
 
index b89c2bf..a1e5a67 100644 (file)
@@ -1644,7 +1644,6 @@ 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
index 911e73b..0e84267 100644 (file)
@@ -337,6 +337,11 @@ static void VerifyNativeContextSeparation(Heap* heap) {
 #endif
 
 
+void MarkCompactCollector::TearDown() {
+  AbortCompaction();
+}
+
+
 void MarkCompactCollector::AddEvacuationCandidate(Page* p) {
   p->MarkEvacuationCandidate();
   evacuation_candidates_.Add(p);
@@ -426,8 +431,8 @@ void MarkCompactCollector::CollectGarbage() {
       heap()->weak_embedded_maps_verification_enabled()) {
     VerifyWeakEmbeddedMapsInOptimizedCode();
   }
-  if (FLAG_collect_maps && FLAG_omit_prototype_checks_for_leaf_maps) {
-    VerifyOmittedPrototypeChecks();
+  if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) {
+    VerifyOmittedMapChecks();
   }
 #endif
 
@@ -498,13 +503,13 @@ void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() {
 }
 
 
-void MarkCompactCollector::VerifyOmittedPrototypeChecks() {
+void MarkCompactCollector::VerifyOmittedMapChecks() {
   HeapObjectIterator iterator(heap()->map_space());
   for (HeapObject* obj = iterator.Next();
        obj != NULL;
        obj = iterator.Next()) {
     Map* map = Map::cast(obj);
-    map->VerifyOmittedPrototypeChecks();
+    map->VerifyOmittedMapChecks();
   }
 }
 #endif  // VERIFY_HEAP
index 3c4dfb6..ee845a0 100644 (file)
@@ -571,6 +571,8 @@ class MarkCompactCollector {
 
   static void Initialize();
 
+  void TearDown();
+
   void CollectEvacuationCandidates(PagedSpace* space);
 
   void AddEvacuationCandidate(Page* p);
@@ -636,7 +638,7 @@ class MarkCompactCollector {
   static void VerifyMarkbitsAreClean(PagedSpace* space);
   static void VerifyMarkbitsAreClean(NewSpace* space);
   void VerifyWeakEmbeddedMapsInOptimizedCode();
-  void VerifyOmittedPrototypeChecks();
+  void VerifyOmittedMapChecks();
 #endif
 
   // Sweep a single page from the given space conservatively.
index 92ac1bc..2debbf8 100644 (file)
@@ -126,6 +126,7 @@ var kMessages = {
 
   stack_overflow:                ["Maximum call stack size exceeded"],
   invalid_time_value:            ["Invalid time value"],
+  invalid_count_value:           ["Invalid count value"],
   // SyntaxError
   paren_in_arg_string:           ["Function arg string contains parenthesis"],
   not_isvar:                     ["builtin %IS_VAR: not a variable"],
@@ -227,16 +228,18 @@ function NoSideEffectToString(obj) {
       }
     }
   }
-  if (IsNativeErrorObject(obj)) return %_CallFunction(obj, ErrorToString);
+  if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
+    return %_CallFunction(obj, ErrorToString);
+  }
   return %_CallFunction(obj, ObjectToString);
 }
 
-
-// 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) {
+// 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) {
   switch (%_ClassOf(obj)) {
     case 'Error':
     case 'EvalError':
@@ -247,7 +250,9 @@ function IsNativeErrorObject(obj) {
     case 'URIError':
       return true;
   }
-  return false;
+
+  var objToString = %GetDataProperty(obj, "toString");
+  return obj instanceof $Error && objToString === ErrorToString;
 }
 
 
@@ -256,7 +261,7 @@ function IsNativeErrorObject(obj) {
 // the error to string method. This is to avoid leaking error
 // objects between script tags in a browser setting.
 function ToStringCheckErrorObject(obj) {
-  if (IsNativeErrorObject(obj)) {
+  if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
     return %_CallFunction(obj, ErrorToString);
   } else {
     return ToString(obj);
index 8d533b3..cb0896a 100644 (file)
@@ -358,6 +358,11 @@ 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:
index 3f5dca0..d424cbc 100644 (file)
@@ -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, "Unexpected initial map for InternalArray function",
+    __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
               t0, Operand(zero_reg));
     __ GetObjectType(a2, a3, t0);
-    __ Assert(eq, "Unexpected initial map for InternalArray function",
+    __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
               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, "Unexpected initial map for Array function (1)",
+    __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
               t0, Operand(zero_reg));
     __ GetObjectType(a2, a3, t0);
-    __ Assert(eq, "Unexpected initial map for Array function (2)",
+    __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
               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, "Unexpected String function", function, Operand(a2));
+    __ Assert(eq, kUnexpectedStringFunction, 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, "Unexpected string wrapper instance size",
+    __ Assert(eq, kUnexpectedStringWrapperInstanceSize,
         t0, Operand(JSValue::kSize >> kPointerSizeLog2));
     __ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
-    __ Assert(eq, "Unexpected unused properties of string wrapper",
+    __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper,
         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, "Unexpected number of pre-allocated property fields.",
+          __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
               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, "Property allocation count failed.",
+      __ Assert(greater_equal, kPropertyAllocationCountFailed,
           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, "Undefined value not loaded.", t7, Operand(t8));
+          __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t8));
         }
         __ jmp(&entry);
         __ bind(&loop);
index 0e1b224..8a03a9a 100644 (file)
@@ -247,17 +247,6 @@ 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) {
@@ -520,8 +509,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
   Label after_sentinel;
   __ JumpIfNotSmi(a3, &after_sentinel);
   if (FLAG_debug_code) {
-    const char* message = "Expected 0 as a Smi sentinel";
-    __ Assert(eq, message, a3, Operand(zero_reg));
+    __ Assert(eq, kExpected0AsASmiSentinel, a3, Operand(zero_reg));
   }
   __ lw(a3, GlobalObjectOperand());
   __ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset));
@@ -679,7 +667,7 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
                                      Label* not_number) {
   __ AssertRootValue(heap_number_map,
                      Heap::kHeapNumberMapRootIndex,
-                     "HeapNumberMap register clobbered.");
+                     kHeapNumberMapRegisterClobbered);
 
   Label is_smi, done;
 
@@ -729,7 +717,7 @@ void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
                                                Label* not_number) {
   __ AssertRootValue(heap_number_map,
                      Heap::kHeapNumberMapRootIndex,
-                     "HeapNumberMap register clobbered.");
+                     kHeapNumberMapRegisterClobbered);
   Label done;
   Label not_in_int32_range;
 
@@ -806,7 +794,7 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
   __ bind(&obj_is_not_smi);
   __ AssertRootValue(heap_number_map,
                      Heap::kHeapNumberMapRootIndex,
-                     "HeapNumberMap register clobbered.");
+                     kHeapNumberMapRegisterClobbered);
   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
 
   // Load the number.
@@ -853,7 +841,7 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
 
   __ AssertRootValue(heap_number_map,
                      Heap::kHeapNumberMapRootIndex,
-                     "HeapNumberMap register clobbered.");
+                     kHeapNumberMapRegisterClobbered);
 
   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined);
 
@@ -4279,12 +4267,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   if (FLAG_debug_code) {
     __ And(t0, regexp_data, Operand(kSmiTagMask));
     __ Check(nz,
-             "Unexpected type for RegExp data, FixedArray expected",
+             kUnexpectedTypeForRegExpDataFixedArrayExpected,
              t0,
              Operand(zero_reg));
     __ GetObjectType(regexp_data, a0, a0);
     __ Check(eq,
-             "Unexpected type for RegExp data, FixedArray expected",
+             kUnexpectedTypeForRegExpDataFixedArrayExpected,
              a0,
              Operand(FIXED_ARRAY_TYPE));
   }
@@ -4639,7 +4627,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
     // Sequential strings have already been ruled out.
     __ And(at, a0, Operand(kIsIndirectStringMask));
     __ Assert(eq,
-              "external string expected, but not found",
+              kExternalStringExpectedButNotFound,
               at,
               Operand(zero_reg));
   }
@@ -5020,7 +5008,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharCodeAtGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
 
   // Index is not a smi.
   __ bind(&index_not_smi_);
@@ -5069,7 +5057,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
 }
 
 
@@ -5106,7 +5094,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharFromCodeGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
 
   __ bind(&slow_case_);
   call_helper.BeforeCall(masm);
@@ -5117,7 +5105,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ Branch(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
 }
 
 
@@ -5172,7 +5160,7 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
     // that it is.
     __ And(scratch4, dest, Operand(kPointerAlignmentMask));
     __ Check(eq,
-             "Destination of copy not aligned.",
+             kDestinationOfCopyNotAligned,
              scratch4,
              Operand(zero_reg));
   }
@@ -5372,7 +5360,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
     // Must be the hole (deleted entry).
     if (FLAG_debug_code) {
       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
-      __ Assert(eq, "oddball in string table is not undefined or the hole",
+      __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole,
           scratch, Operand(candidate));
     }
     __ jmp(&next_probe[i]);
@@ -6580,7 +6568,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, "Received invalid return address.", t0,
+    __ Assert(ne, kReceivedInvalidReturnAddress, t0,
         Operand(reinterpret_cast<uint32_t>(kZapValue)));
   }
   __ Jump(t9);
@@ -7331,7 +7319,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -7386,7 +7374,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -7447,10 +7435,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, "Unexpected initial map for Array function",
+    __ Assert(ne, kUnexpectedInitialMapForArrayFunction,
         at, Operand(zero_reg));
     __ GetObjectType(a3, a3, t0);
-    __ Assert(eq, "Unexpected initial map for Array function",
+    __ Assert(eq, kUnexpectedInitialMapForArrayFunction,
         t0, Operand(MAP_TYPE));
 
     // We should either have undefined in a2 or a valid cell.
@@ -7459,7 +7447,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
     __ Branch(&okay_here, eq, a2, Operand(at));
     __ lw(a3, FieldMemOperand(a2, 0));
-    __ Assert(eq, "Expected property cell in register a2",
+    __ Assert(eq, kExpectedPropertyCellInRegisterA2,
         a3, Operand(cell_map));
     __ bind(&okay_here);
   }
@@ -7559,10 +7547,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, "Unexpected initial map for Array function",
+    __ Assert(ne, kUnexpectedInitialMapForArrayFunction,
         at, Operand(zero_reg));
     __ GetObjectType(a3, a3, t0);
-    __ Assert(eq, "Unexpected initial map for Array function",
+    __ Assert(eq, kUnexpectedInitialMapForArrayFunction,
         t0, Operand(MAP_TYPE));
   }
 
@@ -7579,7 +7567,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
     Label done;
     __ Branch(&done, eq, a3, Operand(FAST_ELEMENTS));
     __ Assert(
-        eq, "Invalid ElementsKind for InternalArray or InternalPackedArray",
+        eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray,
         a3, Operand(FAST_HOLEY_ELEMENTS));
     __ bind(&done);
   }
index 3f74154..10490e7 100644 (file)
@@ -289,7 +289,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
     __ SmiTag(t5);
     __ Or(t5, t5, Operand(1));
     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
-    __ Assert(eq, "object found in smi-only array", at, Operand(t5));
+    __ Assert(eq, kObjectFoundInSmiOnlyArray, 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, "external string expected, but not found",
+    __ Assert(eq, kExternalStringExpectedButNotFound,
         at, Operand(zero_reg));
   }
   // Rule out short external strings.
index 30cc4db..020228f 100644 (file)
@@ -142,8 +142,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
         if ((non_object_regs & (1 << r)) != 0) {
           if (FLAG_debug_code) {
             __ And(at, reg, 0xc0000000);
-            __ Assert(
-                eq, "Unable to encode value as smi", at, Operand(zero_reg));
+            __ Assert(eq, kUnableToEncodeValueAsSmi, at, Operand(zero_reg));
           }
           __ sll(reg, reg, kSmiTagSize);
         }
@@ -325,12 +324,12 @@ void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
 
 
 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on mips");
+  masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnMips);
 }
 
 
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on mips");
+  masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnMips);
 }
 
 
index f6f20cd..437bf3a 100644 (file)
@@ -230,6 +230,11 @@ inline Object* JavaScriptFrame::function_slot_object() const {
 }
 
 
+inline void StackHandler::SetFp(Address slot, Address fp) {
+  Memory::Address_at(slot) = fp;
+}
+
+
 } }  // namespace v8::internal
 
 #endif
index 9c610c3..b60502c 100644 (file)
@@ -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, "Declaration in with context.",
+    __ Check(ne, kDeclarationInWithContext,
         a1, Operand(t0));
     __ LoadRoot(t0, Heap::kCatchContextMapRootIndex);
-    __ Check(ne, "Declaration in catch context.",
+    __ Check(ne, kDeclarationInCatchContext,
         a1, Operand(t0));
   }
 }
@@ -2234,7 +2234,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
 
   Handle<Map> map(isolate()->native_context()->generator_result_map());
 
-  __ Allocate(map->instance_size(), a0, a2, a3, &gc_required, TAG_OBJECT);
+  __ Allocate(map->instance_size(), v0, a2, a3, &gc_required, TAG_OBJECT);
   __ jmp(&allocated);
 
   __ bind(&gc_required);
@@ -2249,19 +2249,18 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   __ li(a3, Operand(isolate()->factory()->ToBoolean(done)));
   __ li(t0, Operand(isolate()->factory()->empty_fixed_array()));
   ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
-  __ sw(a1, FieldMemOperand(a0, HeapObject::kMapOffset));
-  __ sw(t0, FieldMemOperand(a0, JSObject::kPropertiesOffset));
-  __ sw(t0, FieldMemOperand(a0, JSObject::kElementsOffset));
+  __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
+  __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+  __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
   __ sw(a2,
-        FieldMemOperand(a0, JSGeneratorObject::kResultValuePropertyOffset));
+        FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset));
   __ sw(a3,
-        FieldMemOperand(a0, JSGeneratorObject::kResultDonePropertyOffset));
+        FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset));
 
   // Only the value field needs a write barrier, as the other values are in the
   // root set.
-  __ RecordWriteField(a0, JSGeneratorObject::kResultValuePropertyOffset,
+  __ RecordWriteField(v0, JSGeneratorObject::kResultValuePropertyOffset,
                       a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
-  __ mov(result_register(), a0);
 }
 
 
@@ -2530,7 +2529,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         // Check for an uninitialized let binding.
         __ lw(a2, location);
         __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
-        __ Check(eq, "Let binding re-initialization.", a2, Operand(t0));
+        __ Check(eq, kLetBindingReInitialization, a2, Operand(t0));
       }
       // Perform the assignment.
       __ sw(v0, location);
@@ -3493,21 +3492,21 @@ void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
                                                   Register value,
                                                   uint32_t encoding_mask) {
   __ And(at, index, Operand(kSmiTagMask));
-  __ Check(eq, "Non-smi index", at, Operand(zero_reg));
+  __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
   __ And(at, value, Operand(kSmiTagMask));
-  __ Check(eq, "Non-smi value", at, Operand(zero_reg));
+  __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
 
   __ lw(at, FieldMemOperand(string, String::kLengthOffset));
-  __ Check(lt, "Index is too large", index, Operand(at));
+  __ Check(lt, kIndexIsTooLarge, index, Operand(at));
 
-  __ Check(ge, "Index is negative", index, Operand(zero_reg));
+  __ Check(ge, kIndexIsNegative, 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, "Unexpected string type", at, Operand(zero_reg));
+  __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
 }
 
 
@@ -3882,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("Attempt to use undefined cache.");
+    __ Abort(kAttemptToUseUndefinedCache);
     __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
     context()->Plug(v0);
     return;
@@ -4064,7 +4063,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
   //   element: Current array element.
   //   elements_end: Array end.
   if (generate_debug_code_) {
-    __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin",
+    __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin,
         array_length, Operand(zero_reg));
   }
   __ bind(&loop);
@@ -4383,35 +4382,12 @@ 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());
index 8db5f00..34e601c 100644 (file)
@@ -91,7 +91,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
 }
 
 
-void LChunkBuilder::Abort(const char* reason) {
+void LChunkBuilder::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -324,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("Generated code is too large");
+    Abort(kGeneratedCodeIsTooLarge);
   }
 
   if (deopt_jump_table_.length() > 0) {
@@ -411,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("EmitLoadRegister: Unsupported double immediate.");
+      Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
     } else {
       ASSERT(r.IsTagged());
       __ LoadObject(scratch, literal);
@@ -449,9 +449,9 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
       __ cvt_d_w(dbl_scratch, flt_scratch);
       return dbl_scratch;
     } else if (r.IsDouble()) {
-      Abort("unsupported double immediate");
+      Abort(kUnsupportedDoubleImmediate);
     } else if (r.IsTagged()) {
-      Abort("unsupported tagged immediate");
+      Abort(kUnsupportedTaggedImmediate);
     }
   } else if (op->IsStackSlot() || op->IsArgument()) {
     MemOperand mem_op = ToMemOperand(op);
@@ -520,14 +520,14 @@ Operand LCodeGen::ToOperand(LOperand* op) {
       ASSERT(constant->HasInteger32Value());
       return Operand(constant->Integer32Value());
     } else if (r.IsDouble()) {
-      Abort("ToOperand Unsupported double immediate.");
+      Abort(kToOperandUnsupportedDoubleImmediate);
     }
     ASSERT(r.IsTagged());
     return Operand(constant->handle());
   } else if (op->IsRegister()) {
     return Operand(ToRegister(op));
   } else if (op->IsDoubleRegister()) {
-    Abort("ToOperand IsDoubleRegister unimplemented");
+    Abort(kToOperandIsDoubleRegisterUnimplemented);
     return Operand(0);
   }
   // Stack slots not implemented, use ToMemOperand instead.
@@ -748,7 +748,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
   Address entry =
       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
   if (entry == NULL) {
-    Abort("bailout was not prepared");
+    Abort(kBailoutWasNotPrepared);
     return;
   }
 
@@ -1057,20 +1057,16 @@ void LCodeGen::DoModI(LModI* instr) {
   HValue* left = hmod->left();
   HValue* right = hmod->right();
   if (hmod->HasPowerOf2Divisor()) {
-    const Register scratch = scratch0();
     const Register left_reg = ToRegister(instr->left());
-    ASSERT(!left_reg.is(scratch));
     const Register result_reg = ToRegister(instr->result());
 
     // Note: The code below even works when right contains kMinInt.
     int32_t divisor = Abs(right->GetInteger32Constant());
 
-    __ mov(scratch, left_reg);
-
     Label left_is_not_negative, done;
     if (left->CanBeNegative()) {
-      __ Branch(USE_DELAY_SLOT, &left_is_not_negative,
-                ge, left_reg, Operand(zero_reg));
+      __ Branch(left_reg.is(result_reg) ? PROTECT : USE_DELAY_SLOT,
+                &left_is_not_negative, ge, left_reg, Operand(zero_reg));
       __ subu(result_reg, zero_reg, left_reg);
       __ And(result_reg, result_reg, divisor - 1);
       if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
@@ -1081,15 +1077,13 @@ void LCodeGen::DoModI(LModI* instr) {
     }
 
     __ bind(&left_is_not_negative);
-    __ And(result_reg, scratch, divisor - 1);
+    __ And(result_reg, left_reg, divisor - 1);
     __ bind(&done);
 
   } else if (hmod->fixed_right_arg().has_value) {
-    const Register scratch = scratch0();
     const Register left_reg = ToRegister(instr->left());
     const Register result_reg = ToRegister(instr->result());
-
-    Register right_reg = EmitLoadRegister(instr->right(), scratch);
+    const Register right_reg = ToRegister(instr->right());
 
     int32_t divisor = hmod->fixed_right_arg().value;
     ASSERT(IsPowerOf2(divisor));
@@ -1099,8 +1093,8 @@ void LCodeGen::DoModI(LModI* instr) {
 
     Label left_is_not_negative, done;
     if (left->CanBeNegative()) {
-      __ Branch(USE_DELAY_SLOT, &left_is_not_negative,
-                ge, left_reg, Operand(zero_reg));
+      __ Branch(left_reg.is(result_reg) ? PROTECT : USE_DELAY_SLOT,
+                &left_is_not_negative, ge, left_reg, Operand(zero_reg));
       __ subu(result_reg, zero_reg, left_reg);
       __ And(result_reg, result_reg, divisor - 1);
       if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
@@ -1509,7 +1503,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
       __ Or(result, left, right);
       break;
     case Token::BIT_XOR:
-      __ Xor(result, left, right);
+      if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
+        __ Nor(result, zero_reg, left);
+      } else {
+        __ Xor(result, left, right);
+      }
       break;
     default:
       UNREACHABLE();
@@ -1583,8 +1581,12 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
         if (shift_count != 0) {
           if (instr->hydrogen_value()->representation().IsSmi() &&
               instr->can_deopt()) {
-            __ sll(result, left, shift_count - 1);
-            __ SmiTagCheckOverflow(result, result, scratch);
+            if (shift_count != 1) {
+              __ sll(result, left, shift_count - 1);
+              __ SmiTagCheckOverflow(result, result, scratch);
+            } else {
+              __ SmiTagCheckOverflow(result, left, scratch);
+            }
             DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
           } else {
             __ sll(result, left, shift_count);
@@ -1766,7 +1768,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, "Unexpected string type", at, Operand(zero_reg));
+    __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
   }
 
   __ Addu(scratch,
@@ -1783,13 +1785,6 @@ 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);
@@ -2808,19 +2803,6 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
 }
 
 
-void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) {
-  Register object = ToRegister(instr->object());
-  ExternalReference sites_list_address = instr->GetReference(isolate());
-
-  __ li(at, Operand(sites_list_address));
-  __ lw(at, MemOperand(at));
-  __ sw(at, FieldMemOperand(object,
-                            instr->hydrogen()->store_field().offset()));
-  __ li(at, Operand(sites_list_address));
-  __ sw(object, MemOperand(at));
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -3085,7 +3067,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -3171,7 +3153,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -3442,7 +3424,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
 void LCodeGen::DoPushArgument(LPushArgument* instr) {
   LOperand* argument = instr->value();
   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
-    Abort("DoPushArgument not implemented for double type.");
+    Abort(kDoPushArgumentNotImplementedForDoubleType);
   } else {
     Register argument_reg = EmitLoadRegister(argument, at);
     __ push(argument_reg);
@@ -3661,7 +3643,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
     FPURegister input = ToDoubleRegister(instr->value());
     FPURegister result = ToDoubleRegister(instr->result());
     __ abs_d(result, input);
-  } else if (r.IsInteger32()) {
+  } else if (r.IsSmiOrInteger32()) {
     EmitIntegerMathAbs(instr);
   } else {
     // Representation is tagged.
@@ -4267,7 +4249,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -4345,7 +4327,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
     if (constant_key & 0xF0000000) {
-      Abort("array index constant value too big.");
+      Abort(kArrayIndexConstantValueTooBig);
     }
   } else {
     key = ToRegister(instr->key());
@@ -4605,13 +4587,6 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
 }
 
 
-void LCodeGen::DoStringLength(LStringLength* instr) {
-  Register string = ToRegister(instr->string());
-  Register result = ToRegister(instr->result());
-  __ lw(result, FieldMemOperand(string, String::kLengthOffset));
-}
-
-
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
   LOperand* input = instr->value();
   ASSERT(input->IsRegister() || input->IsStackSlot());
@@ -5209,31 +5184,63 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
 }
 
 
-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::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::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();
-  DoCheckMapCommon(map_reg, map, instr->environment());
+  __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
+  if (instr->hydrogen()->has_migration_target()) {
+    __ Branch(deferred->entry());
+  } else {
+    DeoptimizeIf(al, instr->environment());
+  }
+
   __ bind(&success);
 }
 
@@ -5288,25 +5295,6 @@ 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:
@@ -5330,10 +5318,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
   }
   if (instr->size()->IsConstantOperand()) {
@@ -5391,10 +5381,12 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
     __ Push(Smi::FromInt(size));
   }
 
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
   } else {
     CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
index a485b67..670c4cc 100644 (file)
@@ -114,7 +114,7 @@ class LCodeGen BASE_EMBEDDED {
   DoubleRegister EmitLoadDoubleRegister(LOperand* op,
                                         FloatRegister flt_scratch,
                                         DoubleRegister dbl_scratch);
-  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
@@ -153,7 +153,7 @@ class LCodeGen BASE_EMBEDDED {
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
 
-  void DoCheckMapCommon(Register map_reg, Handle<Map> map, LEnvironment* env);
+  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
@@ -213,7 +213,7 @@ class LCodeGen BASE_EMBEDDED {
 
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
   void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
index 771b228..460e13b 100644 (file)
@@ -258,7 +258,7 @@ void LGapResolver::EmitMove(int index) {
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
-    } else if (source->IsDoubleRegister()) {
+    } else if (destination->IsDoubleRegister()) {
       DoubleRegister result = cgen_->ToDoubleRegister(destination);
       double v = cgen_->ToDouble(constant_source);
       __ Move(result, v);
index 5cfca00..38ac19f 100644 (file)
@@ -277,24 +277,6 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) {
 }
 
 
-ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) {
-  switch (hydrogen()->known_list()) {
-    case HLinkObjectInList::ALLOCATION_SITE_LIST:
-      return ExternalReference::allocation_sites_list_address(isolate);
-  }
-
-  UNREACHABLE();
-  // Return a dummy value
-  return ExternalReference::isolate_address(isolate);
-}
-
-
-void LLinkObjectInList::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add(" offset %d", hydrogen()->store_field().offset());
-}
-
-
 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
   context()->PrintTo(stream);
   stream->Add("[%d]", slot_index());
@@ -460,7 +442,7 @@ LPlatformChunk* LChunkBuilder::Build() {
 }
 
 
-void LCodeGen::Abort(const char* reason) {
+void LCodeGen::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -668,7 +650,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
   int vreg = allocator_->GetVirtualRegister();
   if (!allocator_->AllocationOk()) {
-    Abort("Out of virtual registers while trying to allocate temp register.");
+    Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
     vreg = 0;
   }
   operand->set_virtual_register(vreg);
@@ -1345,15 +1327,6 @@ 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);
@@ -1771,17 +1744,6 @@ 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());
@@ -1955,19 +1917,6 @@ 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));
@@ -1976,10 +1925,16 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
 
 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
   LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
-  LInstruction* result = new(zone()) LCheckMaps(value);
-  if (instr->CanOmitMapChecks()) return result;
-  return AssignEnvironment(result);
+  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;
 }
 
 
@@ -2062,13 +2017,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) {
-  LOperand* object = UseRegister(instr->value());
-  LLinkObjectInList* result = new(zone()) LLinkObjectInList(object);
-  return result;
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
@@ -2270,7 +2218,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->transition().is_null() &&
+  bool needs_write_barrier_for_map = instr->has_transition() &&
       instr->NeedsWriteBarrierForMap();
 
   LOperand* obj;
@@ -2341,12 +2289,6 @@ LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
-  LOperand* string = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   info()->MarkAsDeferredCalling();
   LOperand* size = instr->size()->IsConstant()
@@ -2396,7 +2338,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("Too many spill slots needed for OSR");
+    Abort(kTooManySpillSlotsNeededForOSR);
     spill_index = 0;
   }
   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
index 2618c46..a21c323 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -68,7 +67,6 @@ class LCodeGen;
   V(CheckMaps)                                  \
   V(CheckMapValue)                              \
   V(CheckNonSmi)                                \
-  V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
@@ -119,7 +117,6 @@ class LCodeGen;
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
   V(LazyBailout)                                \
-  V(LinkObjectInList)                           \
   V(LoadContextSlot)                            \
   V(LoadExternalArrayPointer)                   \
   V(LoadFieldByIndex)                           \
@@ -175,7 +172,6 @@ class LCodeGen;
   V(StringCharCodeAt)                           \
   V(StringCharFromCode)                         \
   V(StringCompareAndBranch)                     \
-  V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
   V(ThisFunction)                               \
@@ -1358,18 +1354,6 @@ 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) {
@@ -1654,23 +1638,6 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> {
 };
 
 
-class LLinkObjectInList: public LTemplateInstruction<0, 1, 0> {
- public:
-  explicit LLinkObjectInList(LOperand* object) {
-    inputs_[0] = object;
-  }
-
-  LOperand* object() { return inputs_[0]; }
-
-  ExternalReference GetReference(Isolate* isolate);
-
-  DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list")
-  DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList)
-
-  virtual void PrintDataTo(StringStream* stream);
-};
-
-
 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
@@ -2147,7 +2114,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
 
   virtual void PrintDataTo(StringStream* stream);
 
-  Handle<Map> transition() const { return hydrogen()->transition(); }
+  Handle<Map> transition() const { return hydrogen()->transition_map(); }
   Representation representation() const {
     return hydrogen()->field_representation();
   }
@@ -2304,19 +2271,6 @@ class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
 };
 
 
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LStringLength(LOperand* string) {
-    inputs_[0] = string;
-  }
-
-  LOperand* string() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
-  DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
 class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckFunction(LOperand* value) {
@@ -2356,26 +2310,6 @@ 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) {
@@ -2674,7 +2608,7 @@ class LChunkBuilder BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
 
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
index ea08a55..a7ec713 100644 (file)
@@ -256,7 +256,7 @@ void MacroAssembler::RecordWrite(Register object,
   if (emit_debug_code()) {
     lw(at, MemOperand(address));
     Assert(
-        eq, "Wrong address or value passed to RecordWrite", at, Operand(value));
+        eq, kWrongAddressOrValuePassedToRecordWrite, 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, "we should not have an empty lexical context",
+  Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
       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, "JSGlobalObject::native_context should be a native context.",
+    Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
           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, "JSGlobalProxy::context() should not be null.",
+    Check(ne, kJSGlobalProxyContextShouldNotBeNull,
           holder_reg, Operand(at));
 
     lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
     LoadRoot(at, Heap::kNativeContextMapRootIndex);
-    Check(eq, "JSGlobalObject::native_context should be a native context.",
+    Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
           holder_reg, Operand(at));
     // Restore at is not needed. at is reloaded below.
     pop(holder_reg);  // Restore holder.
@@ -2938,7 +2938,7 @@ 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, "Unexpected allocation top", result, Operand(t9));
+      Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
     }
     // Load allocation limit into t9. Result already contains allocation top.
     lw(t9, MemOperand(topaddr, limit - top));
@@ -3008,7 +3008,7 @@ 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, "Unexpected allocation top", result, Operand(t9));
+      Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
     }
     // Load allocation limit into t9. Result already contains allocation top.
     lw(t9, MemOperand(topaddr, limit - top));
@@ -3028,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, "Unaligned allocation in new space", t9, Operand(zero_reg));
+    Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg));
   }
   sw(scratch2, MemOperand(topaddr));
 
@@ -3050,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, "Undo allocation of non allocated memory",
+  Check(less, kUndoAllocationOfNonAllocatedMemory,
       object, Operand(scratch));
 #endif
   // Write the address of the object to un-allocate as the current top.
@@ -3303,7 +3303,7 @@ void MacroAssembler::CopyBytes(Register src,
   bind(&word_loop);
   if (emit_debug_code()) {
     And(scratch, src, kPointerSize - 1);
-    Assert(eq, "Expecting alignment for CopyBytes",
+    Assert(eq, kExpectingAlignmentForCopyBytes,
         scratch, Operand(zero_reg));
   }
   Branch(&byte_loop, lt, length, Operand(kPointerSize));
@@ -4029,7 +4029,7 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
   sw(s0, MemOperand(s3, kNextOffset));
   if (emit_debug_code()) {
     lw(a1, MemOperand(s3, kLevelOffset));
-    Check(eq, "Unexpected level after return from api call", a1, Operand(s2));
+    Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2));
   }
   Subu(s2, s2, Operand(1));
   sw(s2, MemOperand(s3, kLevelOffset));
@@ -4383,10 +4383,10 @@ void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
 // -----------------------------------------------------------------------------
 // Debugging.
 
-void MacroAssembler::Assert(Condition cc, const char* msg,
+void MacroAssembler::Assert(Condition cc, BailoutReason reason,
                             Register rs, Operand rt) {
   if (emit_debug_code())
-    Check(cc, msg, rs, rt);
+    Check(cc, reason, rs, rt);
 }
 
 
@@ -4394,7 +4394,7 @@ void MacroAssembler::AssertRegisterIsRoot(Register reg,
                                           Heap::RootListIndex index) {
   if (emit_debug_code()) {
     LoadRoot(at, index);
-    Check(eq, "Register did not match expected root", reg, Operand(at));
+    Check(eq, kRegisterDidNotMatchExpectedRoot, reg, Operand(at));
   }
 }
 
@@ -4411,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("JSObject with fast elements map has slow elements");
+    Abort(kJSObjectWithFastElementsMapHasSlowElements);
     bind(&ok);
     pop(elements);
   }
 }
 
 
-void MacroAssembler::Check(Condition cc, const char* msg,
+void MacroAssembler::Check(Condition cc, BailoutReason reason,
                            Register rs, Operand rt) {
   Label L;
   Branch(&L, cc, rs, rt);
-  Abort(msg);
+  Abort(reason);
   // Will not return here.
   bind(&L);
 }
 
 
-void MacroAssembler::Abort(const char* msg) {
+void MacroAssembler::Abort(BailoutReason reason) {
   Label abort_start;
   bind(&abort_start);
   // We want to pass the msg string like a smi to avoid GC
@@ -4436,6 +4436,7 @@ void MacroAssembler::Abort(const char* msg) {
   // 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());
@@ -4579,7 +4580,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
     Branch(&ok);
     bind(&fail);
-    Abort("Global functions must have initial map");
+    Abort(kGlobalFunctionsMustHaveInitialMap);
     bind(&ok);
   }
 }
@@ -4862,7 +4863,7 @@ void MacroAssembler::AssertNotSmi(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     andi(at, object, kSmiTagMask);
-    Check(ne, "Operand is a smi", at, Operand(zero_reg));
+    Check(ne, kOperandIsASmi, at, Operand(zero_reg));
   }
 }
 
@@ -4871,7 +4872,7 @@ void MacroAssembler::AssertSmi(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     andi(at, object, kSmiTagMask);
-    Check(eq, "Operand is a smi", at, Operand(zero_reg));
+    Check(eq, kOperandIsASmi, at, Operand(zero_reg));
   }
 }
 
@@ -4880,11 +4881,11 @@ void MacroAssembler::AssertString(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     And(t0, object, Operand(kSmiTagMask));
-    Check(ne, "Operand is a smi and not a string", t0, Operand(zero_reg));
+    Check(ne, kOperandIsASmiAndNotAString, t0, Operand(zero_reg));
     push(object);
     lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
     lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
-    Check(lo, "Operand is not a string", object, Operand(FIRST_NONSTRING_TYPE));
+    Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE));
     pop(object);
   }
 }
@@ -4894,11 +4895,11 @@ void MacroAssembler::AssertName(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
     And(t0, object, Operand(kSmiTagMask));
-    Check(ne, "Operand is a smi and not a name", t0, Operand(zero_reg));
+    Check(ne, kOperandIsASmiAndNotAName, t0, Operand(zero_reg));
     push(object);
     lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
     lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
-    Check(le, "Operand is not a name", object, Operand(LAST_NAME_TYPE));
+    Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE));
     pop(object);
   }
 }
@@ -4906,11 +4907,11 @@ void MacroAssembler::AssertName(Register object) {
 
 void MacroAssembler::AssertRootValue(Register src,
                                      Heap::RootListIndex root_value_index,
-                                     const char* message) {
+                                     BailoutReason reason) {
   if (emit_debug_code()) {
     ASSERT(!src.is(at));
     LoadRoot(at, root_value_index);
-    Check(eq, message, src, Operand(at));
+    Check(eq, reason, src, Operand(at));
   }
 }
 
@@ -5127,7 +5128,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, "The instruction to patch should be a lui.",
+    Check(eq, kTheInstructionToPatchShouldBeALui,
         scratch, Operand(LUI));
     lw(scratch, MemOperand(li_location));
   }
@@ -5139,7 +5140,7 @@ void MacroAssembler::PatchRelocatedValue(Register li_location,
   // scratch is now ori(at, ...).
   if (emit_debug_code()) {
     And(scratch, scratch, kOpcodeMask);
-    Check(eq, "The instruction to patch should be an ori.",
+    Check(eq, kTheInstructionToPatchShouldBeAnOri,
         scratch, Operand(ORI));
     lw(scratch, MemOperand(li_location, kInstrSize));
   }
@@ -5156,7 +5157,7 @@ void MacroAssembler::GetRelocatedValue(Register li_location,
   lw(value, MemOperand(li_location));
   if (emit_debug_code()) {
     And(value, value, kOpcodeMask);
-    Check(eq, "The instruction should be a lui.",
+    Check(eq, kTheInstructionShouldBeALui,
         value, Operand(LUI));
     lw(value, MemOperand(li_location));
   }
@@ -5167,7 +5168,7 @@ void MacroAssembler::GetRelocatedValue(Register li_location,
   lw(scratch, MemOperand(li_location, kInstrSize));
   if (emit_debug_code()) {
     And(scratch, scratch, kOpcodeMask);
-    Check(eq, "The instruction should be an ori.",
+    Check(eq, kTheInstructionShouldBeAnOri,
         scratch, Operand(ORI));
     lw(scratch, MemOperand(li_location, kInstrSize));
   }
index bc3e7c4..ac37db2 100644 (file)
@@ -627,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);
@@ -676,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) {
@@ -1286,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, const char* msg, Register rs, Operand rt);
+  void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt);
   void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
   void AssertFastElements(Register elements);
 
   // Like Assert(), but always enabled.
-  void Check(Condition cc, const char* msg, Register rs, Operand rt);
+  void Check(Condition cc, BailoutReason reason, Register rs, Operand rt);
 
   // Print a message to stdout and abort execution.
-  void Abort(const char* msg);
+  void Abort(BailoutReason msg);
 
   // Verify restrictions about code generated in stubs.
   void set_generating_stub(bool value) { generating_stub_ = value; }
@@ -1378,7 +1378,7 @@ class MacroAssembler: public Assembler {
   // enabled via --debug-code.
   void AssertRootValue(Register src,
                        Heap::RootListIndex root_value_index,
-                       const char* message);
+                       BailoutReason reason);
 
   // ---------------------------------------------------------------------------
   // HeapNumber utilities.
index a5c12bf..f5e0d9d 100644 (file)
@@ -394,7 +394,10 @@ function ObjectGetNotifier(object) {
   if (ObjectIsFrozen(object)) return null;
 
   var objectInfo = objectInfoMap.get(object);
-  if (IS_UNDEFINED(objectInfo)) objectInfo = CreateObjectInfo(object);
+  if (IS_UNDEFINED(objectInfo)) {
+    objectInfo = CreateObjectInfo(object);
+    %SetIsObserved(object);
+  }
 
   if (IS_NULL(objectInfo.notifier)) {
     objectInfo.notifier = { __proto__: notifierPrototype };
index cb5f2b7..e0cb8c9 100644 (file)
@@ -366,9 +366,12 @@ void Map::SharedMapVerify() {
 }
 
 
-void Map::VerifyOmittedPrototypeChecks() {
-  if (!FLAG_omit_prototype_checks_for_leaf_maps) return;
-  if (HasTransitionArray() || is_dictionary_map()) {
+void Map::VerifyOmittedMapChecks() {
+  if (!FLAG_omit_map_checks_for_leaf_maps) return;
+  if (!is_stable() ||
+      is_deprecated() ||
+      HasTransitionArray() ||
+      is_dictionary_map()) {
     CHECK_EQ(0, dependent_code()->number_of_entries(
         DependentCode::kPrototypeCheckGroup));
   }
@@ -1162,10 +1165,6 @@ static bool CheckOneBackPointer(Map* current_map, Object* target) {
 
 
 bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
-  if (HasElementsTransition() &&
-      !CheckOneBackPointer(current_map, elements_transition())) {
-    return false;
-  }
   for (int i = 0; i < number_of_transitions(); ++i) {
     if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
   }
index ef30496..1694757 100644 (file)
@@ -3563,6 +3563,7 @@ bool Map::is_shared() {
 
 
 void Map::set_dictionary_map(bool value) {
+  if (value) mark_unstable();
   set_bit_field3(DictionaryMap::update(bit_field3(), value));
 }
 
@@ -3616,6 +3617,17 @@ 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));
 }
@@ -3626,6 +3638,16 @@ bool Map::is_frozen() {
 }
 
 
+void Map::mark_unstable() {
+  set_bit_field3(IsUnstable::update(bit_field3(), true));
+}
+
+
+bool Map::is_stable() {
+  return !IsUnstable::decode(bit_field3());
+}
+
+
 bool Map::has_code_cache() {
   return code_cache() != GetIsolate()->heap()->empty_fixed_array();
 }
@@ -3657,21 +3679,17 @@ bool Map::CanBeDeprecated() {
 
 
 void Map::NotifyLeafMapLayoutChange() {
-  dependent_code()->DeoptimizeDependentCodeGroup(
-      GetIsolate(),
-      DependentCode::kPrototypeCheckGroup);
-}
-
-
-bool Map::CanOmitPrototypeChecks() {
-  return !HasTransitionArray() && !is_dictionary_map() &&
-         FLAG_omit_prototype_checks_for_leaf_maps;
+  if (is_stable()) {
+    mark_unstable();
+    dependent_code()->DeoptimizeDependentCodeGroup(
+        GetIsolate(),
+        DependentCode::kPrototypeCheckGroup);
+  }
 }
 
 
 bool Map::CanOmitMapChecks() {
-  return !HasTransitionArray() && !is_dictionary_map() &&
-         FLAG_omit_map_checks_for_leaf_maps;
+  return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
 }
 
 
@@ -3804,7 +3822,6 @@ 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 ||
@@ -3819,7 +3836,6 @@ 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 ||
@@ -4009,21 +4025,6 @@ 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();
 }
@@ -4208,7 +4209,20 @@ void Map::InitializeDescriptors(DescriptorArray* descriptors) {
 
 
 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
-SMI_ACCESSORS(Map, bit_field3, kBitField3Offset)
+
+
+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();
+}
 
 
 void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
@@ -4257,7 +4271,8 @@ bool Map::HasTransitionArray() {
 
 
 Map* Map::elements_transition_map() {
-  return transitions()->elements_transition();
+  int index = transitions()->Search(GetHeap()->elements_transition_symbol());
+  return transitions()->GetTarget(index);
 }
 
 
@@ -4288,10 +4303,14 @@ Map* Map::GetTransition(int transition_index) {
 
 
 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
-  MaybeObject* allow_elements = EnsureHasTransitionArray(this);
-  if (allow_elements->IsFailure()) return allow_elements;
-  transitions()->set_elements_transition(transitioned_map);
-  return this;
+  TransitionArray* transitions;
+  MaybeObject* maybe_transitions = AddTransition(
+      GetHeap()->elements_transition_symbol(),
+      transitioned_map,
+      FULL_TRANSITION);
+  if (!maybe_transitions->To(&transitions)) return maybe_transitions;
+  set_transitions(transitions);
+  return transitions;
 }
 
 
@@ -4487,6 +4506,7 @@ ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
                  kEvalFrominstructionsOffsetOffset)
 ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
+BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
 
 Script::CompilationType Script::compilation_type() {
   return BooleanBit::get(flags(), kCompilationTypeBit) ?
index 6b2a3f0..87b2811 100644 (file)
@@ -180,6 +180,12 @@ void HeapObject::HeapObjectPrint(FILE* out) {
     case JS_FUNCTION_PROXY_TYPE:
       JSFunctionProxy::cast(this)->JSFunctionProxyPrint(out);
       break;
+    case JS_SET_TYPE:
+      JSSet::cast(this)->JSSetPrint(out);
+      break;
+    case JS_MAP_TYPE:
+      JSMap::cast(this)->JSMapPrint(out);
+      break;
     case JS_WEAK_MAP_TYPE:
       JSWeakMap::cast(this)->JSWeakMapPrint(out);
       break;
@@ -488,7 +494,7 @@ void JSObject::JSObjectPrint(FILE* out) {
 
 void JSModule::JSModulePrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSModule");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - context = ");
   context()->Print(out);
   PrintF(out, " - scope_info = ");
@@ -561,6 +567,8 @@ static const char* TypeToString(InstanceType type) {
     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";
@@ -777,7 +785,7 @@ static const char* const weekdays[] = {
 
 void JSDate::JSDatePrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSDate");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - value = ");
   value()->Print(out);
   if (!year()->IsSmi()) {
@@ -797,7 +805,7 @@ void JSDate::JSDatePrint(FILE* out) {
 
 void JSProxy::JSProxyPrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSProxy");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - handler = ");
   handler()->Print(out);
   PrintF(out, " - hash = ");
@@ -808,7 +816,7 @@ void JSProxy::JSProxyPrint(FILE* out) {
 
 void JSFunctionProxy::JSFunctionProxyPrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSFunctionProxy");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - handler = ");
   handler()->Print(out);
   PrintF(out, " - call_trap = ");
@@ -819,9 +827,27 @@ void JSFunctionProxy::JSFunctionProxyPrint(FILE* out) {
 }
 
 
+void JSSet::JSSetPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "JSSet");
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - table = ");
+  table()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
+void JSMap::JSMapPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "JSMap");
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - table = ");
+  table()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
 void JSWeakMap::JSWeakMapPrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSWeakMap");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - table = ");
   table()->ShortPrint(out);
   PrintF(out, "\n");
@@ -830,7 +856,7 @@ void JSWeakMap::JSWeakMapPrint(FILE* out) {
 
 void JSWeakSet::JSWeakSetPrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSWeakSet");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - table = ");
   table()->ShortPrint(out);
   PrintF(out, "\n");
@@ -839,8 +865,8 @@ void JSWeakSet::JSWeakSetPrint(FILE* out) {
 
 void JSArrayBuffer::JSArrayBufferPrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSArrayBuffer");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
-  PrintF(out, " - backing_store = -0x%p\n", backing_store());
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - backing_store = %p\n", backing_store());
   PrintF(out, " - byte_length = ");
   byte_length()->ShortPrint(out);
   PrintF(out, "\n");
@@ -878,7 +904,7 @@ void JSDataView::JSDataViewPrint(FILE* out) {
 
 void JSFunction::JSFunctionPrint(FILE* out) {
   HeapObject::PrintHeader(out, "Function");
-  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
   PrintF(out, " - initial_map = ");
   if (has_initial_map()) {
     initial_map()->ShortPrint(out);
index 32e457b..2175737 100644 (file)
@@ -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);
index 7839faa..734bf40 100644 (file)
@@ -2486,8 +2486,7 @@ void Map::DeprecateTransitionTree() {
   deprecate();
   dependent_code()->DeoptimizeDependentCodeGroup(
       GetIsolate(), DependentCode::kTransitionGroup);
-  dependent_code()->DeoptimizeDependentCodeGroup(
-      GetIsolate(), DependentCode::kPrototypeCheckGroup);
+  NotifyLeafMapLayoutChange();
 }
 
 
@@ -2720,6 +2719,7 @@ 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);
@@ -3949,7 +3949,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
   Handle<Object> hresult;
   if (!result->ToHandle(&hresult, isolate)) return result;
 
-  if (FLAG_harmony_observation && map()->is_observed()) {
+  if (FLAG_harmony_observation && self->map()->is_observed()) {
     if (lookup->IsTransition()) {
       EnqueueChangeRecord(self, "new", name, old_value);
     } else {
@@ -6495,6 +6495,7 @@ MaybeObject* Map::RawCopy(int instance_size) {
   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
   new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
   new_bit_field3 = Deprecated::update(new_bit_field3, false);
+  new_bit_field3 = IsUnstable::update(new_bit_field3, false);
   result->set_bit_field3(new_bit_field3);
   return result;
 }
@@ -6517,6 +6518,7 @@ 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()) {
@@ -7023,12 +7025,6 @@ class IntrusiveMapTransitionIterator {
       return transition_array_->GetTarget(index);
     }
 
-    if (index == number_of_transitions &&
-        transition_array_->HasElementsTransition()) {
-      Map* elements_transition = transition_array_->elements_transition();
-      *TransitionArrayHeader() = Smi::FromInt(index + 1);
-      return elements_transition;
-    }
     *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
     return NULL;
   }
@@ -9145,18 +9141,10 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
     }
   }
 
-  if (t->HasElementsTransition() &&
-      ClearBackPointer(heap, t->elements_transition())) {
-    if (t->elements_transition()->instance_descriptors() == descriptors) {
-      descriptors_owner_died = true;
-    }
-    t->ClearElementsTransition();
-  } else {
-    // If there are no transitions to be cleared, return.
-    // TODO(verwaest) Should be an assert, otherwise back pointers are not
-    // properly cleared.
-    if (transition_index == t->number_of_transitions()) return;
-  }
+  // If there are no transitions to be cleared, return.
+  // TODO(verwaest) Should be an assert, otherwise back pointers are not
+  // properly cleared.
+  if (transition_index == t->number_of_transitions()) return;
 
   int number_of_own_descriptors = NumberOfOwnDescriptors();
 
@@ -9818,7 +9806,7 @@ void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
 }
 
 
-void SharedFunctionInfo::DisableOptimization(const char* reason) {
+void SharedFunctionInfo::DisableOptimization(BailoutReason 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
@@ -9836,7 +9824,7 @@ void SharedFunctionInfo::DisableOptimization(const char* reason) {
   if (FLAG_trace_opt) {
     PrintF("[disabled optimization for ");
     ShortPrint();
-    PrintF(", reason: %s]\n", reason);
+    PrintF(", reason: %s]\n", GetBailoutReason(reason));
   }
 }
 
@@ -10807,18 +10795,17 @@ 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()) {
-      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);
+      FullCodeGenerator::BackEdgeTableIterator back_edges(this);
+
+      PrintF(out, "Back edges (size = %u)\n", back_edges.table_length());
       PrintF(out, "ast_id  pc_offset  loop_depth\n");
-      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;
+
+      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());
       }
+
       PrintF(out, "\n");
     }
 #ifdef OBJECT_PRINT
@@ -15978,4 +15965,15 @@ 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
index 3881874..b2dc181 100644 (file)
@@ -1046,7 +1046,287 @@ class MaybeObject BASE_EMBEDDED {
   V(AccessCheckNeeded)                         \
   V(Cell)                                      \
   V(PropertyCell)                              \
-  V(ObjectHashTable)                           \
+  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(kBailedOutDueToDependentMap, "bailed out due to dependent map")           \
+  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);
 
 
 // Object is the abstract superclass for all classes in the
@@ -4501,7 +4781,6 @@ 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)     \
@@ -4620,8 +4899,7 @@ 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 ||
-           kind == UNARY_OP_IC;
+    return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC;
   }
 
   inline StubType type();  // Only valid for monomorphic IC stubs.
@@ -4636,7 +4914,6 @@ 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; }
@@ -4710,10 +4987,6 @@ 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();
 
@@ -4952,9 +5225,6 @@ 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;
@@ -4963,15 +5233,12 @@ 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,
@@ -5176,8 +5443,8 @@ class Map: public HeapObject {
   inline void set_bit_field2(byte value);
 
   // Bit field 3.
-  inline int bit_field3();
-  inline void set_bit_field3(int value);
+  inline uint32_t bit_field3();
+  inline void set_bit_field3(uint32_t bits);
 
   class EnumLengthBits:             public BitField<int,   0, 11> {};
   class NumberOfOwnDescriptorsBits: public BitField<int,  11, 11> {};
@@ -5188,6 +5455,8 @@ class Map: public HeapObject {
   class IsObserved:                 public BitField<bool, 26,  1> {};
   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
@@ -5492,6 +5761,10 @@ class Map: public HeapObject {
   inline void set_is_observed(bool is_observed);
   inline void freeze();
   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();
@@ -5638,7 +5911,6 @@ class Map: public HeapObject {
   // the descriptor array.
   inline void NotifyLeafMapLayoutChange();
 
-  inline bool CanOmitPrototypeChecks();
   inline bool CanOmitMapChecks();
 
   void AddDependentCompilationInfo(DependentCode::DependencyGroup group,
@@ -5655,7 +5927,7 @@ class Map: public HeapObject {
 
 #ifdef VERIFY_HEAP
   void SharedMapVerify();
-  void VerifyOmittedPrototypeChecks();
+  void VerifyOmittedMapChecks();
 #endif
 
   inline int visitor_id();
@@ -5873,6 +6145,12 @@ class Script: public Struct {
   inline CompilationState compilation_state();
   inline void set_compilation_state(CompilationState state);
 
+  // [is_shared_cross_origin]: An opaque boolean set by the embedder via
+  // ScriptOrigin, and used by the embedder to make decisions about the
+  // script's level of privilege. V8 just passes this through. Encoded in
+  // the 'flags' field.
+  DECL_BOOLEAN_ACCESSORS(is_shared_cross_origin)
+
   static inline Script* cast(Object* obj);
 
   // If script source is an external string, check that the underlying
@@ -5904,6 +6182,7 @@ class Script: public Struct {
   // Bit positions in the flags field.
   static const int kCompilationTypeBit = 0;
   static const int kCompilationStateBit = 1;
+  static const int kIsSharedCrossOriginBit = 2;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
 };
@@ -6295,7 +6574,7 @@ class SharedFunctionInfo: public HeapObject {
 
   // Disable (further) attempted optimization of all functions sharing this
   // shared function info.
-  void DisableOptimization(const char* reason);
+  void DisableOptimization(BailoutReason 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
@@ -9777,6 +10056,7 @@ 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)")
 
index df568ef..4947790 100644 (file)
@@ -3197,6 +3197,20 @@ 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);
 
index 5c252bb..8856833 100644 (file)
@@ -239,7 +239,8 @@ bool OS::ArmUsingHardFloat() {
 #else
 #if defined(__ARM_PCS_VFP)
   return true;
-#elif defined(__ARM_PCS) || defined(__SOFTFP) || !defined(__VFP_FP__)
+#elif defined(__ARM_PCS) || defined(__SOFTFP__) || defined(__SOFTFP) || \
+      !defined(__VFP_FP__)
   return false;
 #else
 #error "Your version of GCC does not report the FP ABI compiled for."          \
index 4e2e389..e772a54 100644 (file)
@@ -376,8 +376,8 @@ CpuProfile::CpuProfile(const char* title, unsigned uid, bool record_samples)
     : title_(title),
       uid_(uid),
       record_samples_(record_samples),
-      start_time_ms_(OS::TimeCurrentMillis()),
-      end_time_ms_(0) {
+      start_time_us_(OS::Ticks()),
+      end_time_us_(0) {
 }
 
 
@@ -388,13 +388,13 @@ void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
 
 
 void CpuProfile::CalculateTotalTicksAndSamplingRate() {
-  end_time_ms_ = OS::TimeCurrentMillis();
+  end_time_us_ = OS::Ticks();
   top_down_.CalculateTotalTicks();
 
-  double duration = end_time_ms_ - start_time_ms_;
-  if (duration < 1) duration = 1;
+  double duration_ms = (end_time_us_ - start_time_us_) / 1000.;
+  if (duration_ms < 1) duration_ms = 1;
   unsigned ticks = top_down_.root()->total_ticks();
-  double rate = ticks / duration;
+  double rate = ticks / duration_ms;
   top_down_.SetTickRatePerMs(rate);
 }
 
index 7861ccd..0cc397e 100644 (file)
@@ -209,12 +209,15 @@ class CpuProfile {
   void AddPath(const Vector<CodeEntry*>& path);
   void CalculateTotalTicksAndSamplingRate();
 
-  INLINE(const char* title() const) { return title_; }
-  INLINE(unsigned uid() const) { return uid_; }
-  INLINE(const ProfileTree* top_down() const) { return &top_down_; }
+  const char* title() const { return title_; }
+  unsigned uid() const { return uid_; }
+  const ProfileTree* top_down() const { return &top_down_; }
 
-  INLINE(int samples_count() const) { return samples_.length(); }
-  INLINE(ProfileNode* sample(int index) const) { return samples_.at(index); }
+  int samples_count() const { return samples_.length(); }
+  ProfileNode* sample(int index) const { return samples_.at(index); }
+
+  int64_t start_time_us() const { return start_time_us_; }
+  int64_t end_time_us() const { return end_time_us_; }
 
   void UpdateTicksScale();
 
@@ -225,8 +228,8 @@ class CpuProfile {
   const char* title_;
   unsigned uid_;
   bool record_samples_;
-  double start_time_ms_;
-  double end_time_ms_;
+  int64_t start_time_us_;
+  int64_t end_time_us_;
   List<ProfileNode*> samples_;
   ProfileTree top_down_;
 
index ed3527f..0916b93 100644 (file)
 #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/datefmt.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/uloc.h"
+#include "unicode/uversion.h"
+#endif
+
 #ifndef _STLP_VENDOR_CSTD
 // STLPort doesn't import fpclassify and isless into the std namespace.
 using std::fpclassify;
@@ -680,7 +697,9 @@ void Runtime::FreeArrayBuffer(Isolate* isolate,
   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
       -static_cast<intptr_t>(allocated_length));
   CHECK(V8::ArrayBufferAllocator() != NULL);
-  V8::ArrayBufferAllocator()->Free(phantom_array_buffer->backing_store());
+  V8::ArrayBufferAllocator()->Free(
+      phantom_array_buffer->backing_store(),
+      allocated_length);
 }
 
 
@@ -712,13 +731,18 @@ void Runtime::SetupArrayBuffer(Isolate* isolate,
 bool Runtime::SetupArrayBufferAllocatingData(
     Isolate* isolate,
     Handle<JSArrayBuffer> array_buffer,
-    size_t allocated_length) {
+    size_t allocated_length,
+    bool initialize) {
   void* data;
   CHECK(V8::ArrayBufferAllocator() != NULL);
   if (allocated_length != 0) {
-    data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
+    if (initialize) {
+      data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
+    } else {
+      data =
+        V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
+    }
     if (data == NULL) return false;
-    memset(data, 0, allocated_length);
   } else {
     data = NULL;
   }
@@ -805,74 +829,78 @@ enum TypedArrayId {
   ARRAY_ID_UINT8C = 9
 };
 
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
-  HandleScope scope(isolate);
-  ASSERT(args.length() == 5);
-  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
-  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
-  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
-  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
-
-  ASSERT(holder->GetInternalFieldCount() ==
-      v8::ArrayBufferView::kInternalFieldCount);
-  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
-    holder->SetInternalField(i, Smi::FromInt(0));
-  }
-
-  ExternalArrayType arrayType;
-  size_t elementSize;
+static void ArrayIdToTypeAndSize(
+    int arrayId, ExternalArrayType* array_type, size_t* element_size) {
   switch (arrayId) {
     case ARRAY_ID_UINT8:
-      arrayType = kExternalUnsignedByteArray;
-      elementSize = 1;
+      *array_type = kExternalUnsignedByteArray;
+      *element_size = 1;
       break;
     case ARRAY_ID_INT8:
-      arrayType = kExternalByteArray;
-      elementSize = 1;
+      *array_type = kExternalByteArray;
+      *element_size = 1;
       break;
     case ARRAY_ID_UINT16:
-      arrayType = kExternalUnsignedShortArray;
-      elementSize = 2;
+      *array_type = kExternalUnsignedShortArray;
+      *element_size = 2;
       break;
     case ARRAY_ID_INT16:
-      arrayType = kExternalShortArray;
-      elementSize = 2;
+      *array_type = kExternalShortArray;
+      *element_size = 2;
       break;
     case ARRAY_ID_UINT32:
-      arrayType = kExternalUnsignedIntArray;
-      elementSize = 4;
+      *array_type = kExternalUnsignedIntArray;
+      *element_size = 4;
       break;
     case ARRAY_ID_INT32:
-      arrayType = kExternalIntArray;
-      elementSize = 4;
+      *array_type = kExternalIntArray;
+      *element_size = 4;
       break;
     case ARRAY_ID_FLOAT32:
-      arrayType = kExternalFloatArray;
-      elementSize = 4;
+      *array_type = kExternalFloatArray;
+      *element_size = 4;
       break;
     case ARRAY_ID_FLOAT64:
-      arrayType = kExternalDoubleArray;
-      elementSize = 8;
+      *array_type = kExternalDoubleArray;
+      *element_size = 8;
       break;
     case ARRAY_ID_UINT8C:
-      arrayType = kExternalPixelArray;
-      elementSize = 1;
+      *array_type = kExternalPixelArray;
+      *element_size = 1;
       break;
     default:
       UNREACHABLE();
-      return NULL;
+  }
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 5);
+  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
+  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
+  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
+  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
+
+  ASSERT(holder->GetInternalFieldCount() ==
+      v8::ArrayBufferView::kInternalFieldCount);
+  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
+    holder->SetInternalField(i, Smi::FromInt(0));
   }
 
+  ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
+  size_t element_size = 1;  // Bogus initialization.
+  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+
   holder->set_buffer(*buffer);
   holder->set_byte_offset(*byte_offset_object);
   holder->set_byte_length(*byte_length_object);
 
   size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
   size_t byte_length = NumberToSize(isolate, *byte_length_object);
-  ASSERT(byte_length % elementSize == 0);
-  size_t length = byte_length / elementSize;
+  ASSERT(byte_length % element_size == 0);
+  size_t length = byte_length / element_size;
 
   Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
   holder->set_length(*length_obj);
@@ -881,13 +909,99 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
 
   Handle<ExternalArray> elements =
       isolate->factory()->NewExternalArray(
-          static_cast<int>(length), arrayType,
+          static_cast<int>(length), array_type,
           static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
   holder->set_elements(*elements);
   return isolate->heap()->undefined_value();
 }
 
 
+// Initializes a typed array from an array-like object.
+// If an array-like object happens to be a typed array of the same type,
+// initializes backing store using memove.
+//
+// Returns true if backing store was initialized or false otherwise.
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 4);
+  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
+  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
+  CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
+
+  ASSERT(holder->GetInternalFieldCount() ==
+      v8::ArrayBufferView::kInternalFieldCount);
+  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
+    holder->SetInternalField(i, Smi::FromInt(0));
+  }
+
+  ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
+  size_t element_size = 1;  // Bogus initialization.
+  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+
+  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
+  size_t length = NumberToSize(isolate, *length_obj);
+  size_t byte_length = length * element_size;
+  if (byte_length < length) {  // Overflow
+    return isolate->Throw(*isolate->factory()->
+          NewRangeError("invalid_array_buffer_length",
+            HandleVector<Object>(NULL, 0)));
+  }
+
+  // We assume that the caller of this function will initialize holder
+  // with the loop
+  //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
+  // If source is a typed array, this loop will always run to completion,
+  // so we are sure that the backing store will be initialized.
+  // Otherwise, we do not know (the indexing operation might throw).
+  // Hence we require zero initialization unless our source is a typed array.
+  bool should_zero_initialize = !source->IsJSTypedArray();
+
+  if (!Runtime::SetupArrayBufferAllocatingData(
+        isolate, buffer, byte_length, should_zero_initialize)) {
+    return isolate->Throw(*isolate->factory()->
+          NewRangeError("invalid_array_buffer_length",
+            HandleVector<Object>(NULL, 0)));
+  }
+
+  holder->set_buffer(*buffer);
+  holder->set_byte_offset(Smi::FromInt(0));
+  Handle<Object> byte_length_obj(
+      isolate->factory()->NewNumberFromSize(byte_length));
+  holder->set_byte_length(*byte_length_obj);
+  holder->set_length(*length_obj);
+  holder->set_weak_next(buffer->weak_first_view());
+  buffer->set_weak_first_view(*holder);
+
+  Handle<ExternalArray> elements =
+      isolate->factory()->NewExternalArray(
+          static_cast<int>(length), array_type,
+          static_cast<uint8_t*>(buffer->backing_store()));
+  holder->set_elements(*elements);
+
+  if (source->IsJSTypedArray()) {
+    Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
+
+    if (typed_array->type() == holder->type()) {
+      uint8_t* backing_store =
+        static_cast<uint8_t*>(
+          JSArrayBuffer::cast(typed_array->buffer())->backing_store());
+      size_t source_byte_offset =
+          NumberToSize(isolate, typed_array->byte_offset());
+      OS::MemCopy(
+          buffer->backing_store(),
+          backing_store + source_byte_offset,
+          byte_length);
+      return *isolate->factory()->true_value();
+    } else {
+      return *isolate->factory()->false_value();
+    }
+  }
+
+  return *isolate->factory()->false_value();
+}
+
+
 #define TYPED_ARRAY_GETTER(getter, accessor) \
   RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) {             \
     HandleScope scope(isolate);                                               \
@@ -907,6 +1021,21 @@ TYPED_ARRAY_GETTER(Length, length)
 
 #undef TYPED_ARRAY_GETTER
 
+// Return codes for Runtime_TypedArraySetFastCases.
+// Should be synchronized with typedarray.js natives.
+enum TypedArraySetResultCodes {
+  // Set from typed array of the same type.
+  // This is processed by TypedArraySetFastCases
+  TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
+  // Set from typed array of the different type, overlapping in memory.
+  TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
+  // Set from typed array of the different type, non-overlapping.
+  TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
+  // Set from non-typed array.
+  TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
+};
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
   HandleScope scope(isolate);
   CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
@@ -918,7 +1047,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
         "not_typed_array", HandleVector<Object>(NULL, 0)));
 
   if (!source_obj->IsJSTypedArray())
-    return isolate->heap()->false_value();
+    return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
 
   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
@@ -933,20 +1062,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
     return isolate->Throw(*isolate->factory()->NewRangeError(
           "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
 
-  Handle<JSArrayBuffer> target_buffer(JSArrayBuffer::cast(target->buffer()));
-  Handle<JSArrayBuffer> source_buffer(JSArrayBuffer::cast(source->buffer()));
   size_t target_offset = NumberToSize(isolate, target->byte_offset());
   size_t source_offset = NumberToSize(isolate, source->byte_offset());
   uint8_t* target_base =
-      static_cast<uint8_t*>(target_buffer->backing_store()) + target_offset;
+      static_cast<uint8_t*>(
+        JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
   uint8_t* source_base =
-      static_cast<uint8_t*>(source_buffer->backing_store()) + source_offset;
+      static_cast<uint8_t*>(
+        JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
 
   // Typed arrays of the same type: use memmove.
   if (target->type() == source->type()) {
     memmove(target_base + offset * target->element_size(),
         source_base, source_byte_length);
-    return isolate->heap()->true_value();
+    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
   }
 
   // Typed arrays of different types over the same backing store
@@ -954,78 +1083,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
         source_base + source_byte_length > target_base) ||
       (target_base <= source_base &&
         target_base + target_byte_length > source_base)) {
-    size_t target_element_size = target->element_size();
-    size_t source_element_size = source->element_size();
-
-    size_t source_length = NumberToSize(isolate, source->length());
-
-    // Copy left part
-    size_t left_index;
-    {
-      // First un-mutated byte after the next write
-      uint8_t* target_ptr = target_base + (offset + 1) * target_element_size;
-      // Next read at source_ptr. We do not care for memory changing before
-      // source_ptr - we have already copied it.
-      uint8_t* source_ptr = source_base;
-      for (left_index = 0;
-           left_index < source_length && target_ptr <= source_ptr;
-           left_index++) {
-        Handle<Object> v = Object::GetElement(
-            source, static_cast<uint32_t>(left_index));
-        JSObject::SetElement(
-            target, static_cast<uint32_t>(offset + left_index), v,
-            NONE, kNonStrictMode);
-        target_ptr += target_element_size;
-        source_ptr += source_element_size;
-      }
-    }
-    // Copy right part
-    size_t right_index;
-    {
-      // First unmutated byte before the next write
-      uint8_t* target_ptr =
-        target_base + (offset + source_length - 1) * target_element_size;
-      // Next read before source_ptr. We do not care for memory changing after
-      // source_ptr - we have already copied it.
-      uint8_t* source_ptr =
-        source_base + source_length * source_element_size;
-      for (right_index = source_length - 1;
-           right_index >= left_index && target_ptr >= source_ptr;
-           right_index--) {
-        Handle<Object> v = Object::GetElement(
-            source, static_cast<uint32_t>(right_index));
-        JSObject::SetElement(
-            target, static_cast<uint32_t>(offset + right_index), v,
-            NONE, kNonStrictMode);
-        target_ptr -= target_element_size;
-        source_ptr -= source_element_size;
-      }
-    }
-    // There can be at most 8 entries left in the middle that need buffering
-    // (because the largest element_size is 8 times the smallest).
-    ASSERT((right_index + 1) - left_index <= 8);
-    Handle<Object> temp[8];
-    size_t idx;
-    for (idx = left_index; idx <= right_index; idx++) {
-      temp[idx - left_index] = Object::GetElement(
-          source, static_cast<uint32_t>(idx));
-    }
-    for (idx = left_index; idx <= right_index; idx++) {
-      JSObject::SetElement(
-          target, static_cast<uint32_t>(offset + idx), temp[idx-left_index],
-          NONE, kNonStrictMode);
-    }
+    // We do not support overlapping ArrayBuffers
+    ASSERT(
+      JSArrayBuffer::cast(target->buffer())->backing_store() ==
+      JSArrayBuffer::cast(source->buffer())->backing_store());
+    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
   } else {  // Non-overlapping typed arrays
-    for (size_t idx = 0; idx < source_length; idx++) {
-      Handle<Object> value = Object::GetElement(
-          source, static_cast<uint32_t>(idx));
-      JSObject::SetElement(
-          target, static_cast<uint32_t>(offset + idx), value,
-          NONE, kNonStrictMode);
-    }
+    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
   }
-
-  return isolate->heap()->true_value();
 }
 
 
@@ -7188,15 +7253,6 @@ 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);
@@ -8499,23 +8555,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
 
     // Use linear search of the unoptimized code's back edge table to find
     // the AST id matching the PC.
-    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 target_pc_offset =
+      static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
     uint32_t loop_depth = 0;
-    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);
+
+    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();
         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);
@@ -8632,8 +8686,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);
-  ASSERT(offset >= 0);
-  ASSERT(argc >= 0);
+  RUNTIME_ASSERT(offset >= 0);
+  RUNTIME_ASSERT(argc >= 0);
 
   // If there are too many arguments, allocate argv via malloc.
   const int argv_small_size = 10;
@@ -9426,7 +9480,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
   ASSERT_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
 
-  source = Handle<String>(source->TryFlattenGetString());
+  source = Handle<String>(FlattenGetString(source));
   // Optimized fast case where we only have ASCII characters.
   Handle<Object> result;
   if (source->IsSeqOneByteString()) {
@@ -13316,6 +13370,304 @@ 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);
+  Handle<Object> result = Utils::OpenPersistent(wrapper);
+  wrapper.ClearAndLeak();
+  return *result;
+}
+
+
+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;
+}
+#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
@@ -13434,6 +13786,18 @@ 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.
@@ -13677,6 +14041,9 @@ 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());
index 17e3b43..ade7e73 100644 (file)
@@ -109,6 +109,7 @@ 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) \
@@ -157,7 +158,6 @@ 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) \
@@ -361,6 +361,7 @@ namespace internal {
   F(ArrayBufferSliceImpl, 3, 1) \
   \
   F(TypedArrayInitialize, 5, 1) \
+  F(TypedArrayInitializeFromArrayLike, 4, 1) \
   F(TypedArrayGetBuffer, 1, 1) \
   F(TypedArrayGetByteLength, 1, 1) \
   F(TypedArrayGetByteOffset, 1, 1) \
@@ -533,6 +534,26 @@ 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) \
+
+#else
+#define RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
+#endif
+
+
 #ifdef DEBUG
 #define RUNTIME_FUNCTION_LIST_DEBUG(F) \
   /* Testing */ \
@@ -550,7 +571,8 @@ 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_DEBUGGER_SUPPORT(F) \
+  RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
 
 // ----------------------------------------------------------------------------
 // INLINE_FUNCTION_LIST defines all inlined functions accessed
@@ -784,7 +806,8 @@ class Runtime : public AllStatic {
   static bool SetupArrayBufferAllocatingData(
       Isolate* isolate,
       Handle<JSArrayBuffer> array_buffer,
-      size_t allocated_length);
+      size_t allocated_length,
+      bool initialize = true);
 
   static void FreeArrayBuffer(
       Isolate* isolate,
index 90fb36b..5339570 100644 (file)
@@ -294,20 +294,6 @@ 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);
index 6e451f0..d72ed1a 100644 (file)
 #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);
index 6c5a620..746c926 100644 (file)
@@ -1304,6 +1304,7 @@ 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());
 
index b47452e..aa864b6 100644 (file)
@@ -784,8 +784,9 @@ 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.
-  static const int kMaxNonCodeHeapObjectSize = kNonCodeObjectAreaSize;
+  // from new space to large object space.  Takes double alignment into account.
+  static const int kMaxNonCodeHeapObjectSize =
+      kNonCodeObjectAreaSize - kPointerSize;
 
   // Page size mask.
   static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
index 45b6457..c4825fc 100644 (file)
@@ -57,30 +57,8 @@ TransitionArray* TransitionArray::cast(Object* object) {
 }
 
 
-Map* TransitionArray::elements_transition() {
-  Object* transition_map = get(kElementsTransitionIndex);
-  return Map::cast(transition_map);
-}
-
-
-void TransitionArray::ClearElementsTransition() {
-  WRITE_FIELD(this, kElementsTransitionOffset, Smi::FromInt(0));
-}
-
-
 bool TransitionArray::HasElementsTransition() {
-  return IsFullTransitionArray() &&
-      get(kElementsTransitionIndex) != Smi::FromInt(0);
-}
-
-
-void TransitionArray::set_elements_transition(Map* transition_map,
-                                              WriteBarrierMode mode) {
-  ASSERT(IsFullTransitionArray());
-  Heap* heap = GetHeap();
-  WRITE_FIELD(this, kElementsTransitionOffset, transition_map);
-  CONDITIONAL_WRITE_BARRIER(
-      heap, this, kElementsTransitionOffset, transition_map, mode);
+  return Search(GetHeap()->elements_transition_symbol()) != kNotFound;
 }
 
 
index df53178..086edcb 100644 (file)
@@ -50,7 +50,6 @@ MaybeObject* TransitionArray::Allocate(int number_of_transitions) {
   FixedArray* array;
   MaybeObject* maybe_array = AllocateRaw(ToKeyIndex(number_of_transitions));
   if (!maybe_array->To(&array)) return maybe_array;
-  array->set(kElementsTransitionIndex, Smi::FromInt(0));
   array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
   return array;
 }
@@ -120,10 +119,6 @@ MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) {
   maybe_array = TransitionArray::Allocate(new_size);
   if (!maybe_array->To(&result)) return maybe_array;
 
-  if (HasElementsTransition()) {
-    result->set_elements_transition(elements_transition());
-  }
-
   if (HasPrototypeTransitions()) {
     result->SetPrototypeTransitions(GetPrototypeTransitions());
   }
index 7abef47..fde1279 100644 (file)
@@ -41,10 +41,10 @@ namespace internal {
 // TransitionArrays are fixed arrays used to hold map transitions for property,
 // constant, and element changes. They can either be simple transition arrays
 // that store a single property transition, or a full transition array that has
-// space for elements transitions, prototype transitions and multiple property
-// transitons. The details related to property transitions are accessed in the
-// descriptor array of the target map. In the case of a simple transition, the
-// key is also read from the descriptor array of the target map.
+// prototype transitions and multiple property transitons. The details related
+// to property transitions are accessed in the descriptor array of the target
+// map. In the case of a simple transition, the key is also read from the
+// descriptor array of the target map.
 //
 // The simple format of the these objects is:
 // [0] Undefined or back pointer map
@@ -52,9 +52,8 @@ namespace internal {
 //
 // The full format is:
 // [0] Undefined or back pointer map
-// [1] Smi(0) or elements transition map
-// [2] Smi(0) or fixed array of prototype transitions
-// [3] First transition
+// [1] Smi(0) or fixed array of prototype transitions
+// [2] First transition
 // [length() - kTransitionSize] Last transition
 class TransitionArray: public FixedArray {
  public:
@@ -73,12 +72,7 @@ class TransitionArray: public FixedArray {
 
   inline PropertyDetails GetTargetDetails(int transition_number);
 
-  inline Map* elements_transition();
-  inline void set_elements_transition(
-      Map* target,
-      WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
   inline bool HasElementsTransition();
-  inline void ClearElementsTransition();
 
   inline Object* back_pointer_storage();
   inline void set_back_pointer_storage(
@@ -127,8 +121,21 @@ class TransitionArray: public FixedArray {
   // Allocates a TransitionArray.
   MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
 
-  bool IsSimpleTransition() { return length() == kSimpleTransitionSize; }
-  bool IsFullTransitionArray() { return length() >= kFirstIndex; }
+  bool IsSimpleTransition() {
+    return length() == kSimpleTransitionSize &&
+        get(kSimpleTransitionTarget)->IsHeapObject() &&
+        // The IntrusivePrototypeTransitionIterator may have set the map of the
+        // prototype transitions array to a smi. In that case, there are
+        // prototype transitions, hence this transition array is a full
+        // transition array.
+        HeapObject::cast(get(kSimpleTransitionTarget))->map()->IsMap() &&
+        get(kSimpleTransitionTarget)->IsMap();
+  }
+
+  bool IsFullTransitionArray() {
+    return length() > kFirstIndex ||
+        (length() == kFirstIndex && !IsSimpleTransition());
+  }
 
   // Casting.
   static inline TransitionArray* cast(Object* obj);
@@ -139,9 +146,8 @@ class TransitionArray: public FixedArray {
   static const int kBackPointerStorageIndex = 0;
 
   // Layout for full transition arrays.
-  static const int kElementsTransitionIndex = 1;
-  static const int kPrototypeTransitionsIndex = 2;
-  static const int kFirstIndex = 3;
+  static const int kPrototypeTransitionsIndex = 1;
+  static const int kFirstIndex = 2;
 
   // Layout for simple transition arrays.
   static const int kSimpleTransitionTarget = 1;
@@ -152,9 +158,7 @@ class TransitionArray: public FixedArray {
   static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
 
   // Layout for the full transition array header.
-  static const int kElementsTransitionOffset = kBackPointerStorageOffset +
-                                               kPointerSize;
-  static const int kPrototypeTransitionsOffset = kElementsTransitionOffset +
+  static const int kPrototypeTransitionsOffset = kBackPointerStorageOffset +
                                                  kPointerSize;
 
   // Layout of map transition entries in full transition arrays.
index 769df07..336b459 100644 (file)
@@ -384,17 +384,6 @@ 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,
@@ -658,7 +647,6 @@ 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:
index 1a7c67d..4b376c8 100644 (file)
@@ -297,7 +297,6 @@ 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,
index d5357b4..7bd16f6 100644 (file)
@@ -77,11 +77,10 @@ function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
   function ConstructByArrayLike(obj, arrayLike) {
     var length = arrayLike.length;
     var l =  ToPositiveInteger(length, "invalid_typed_array_length");
-    var byteLength = l * elementSize;
-    var buffer = new $ArrayBuffer(byteLength);
-    %TypedArrayInitialize(obj, arrayId, buffer, 0, byteLength);
-    for (var i = 0; i < l; i++) {
-      obj[i] = arrayLike[i];
+    if(!%TypedArrayInitializeFromArrayLike(obj, arrayId, arrayLike, l)) {
+      for (var i = 0; i < l; i++) {
+        obj[i] = arrayLike[i];
+      }
     }
   }
 
@@ -144,30 +143,103 @@ function CreateSubArray(elementSize, constructor) {
   }
 }
 
+function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
+  if (offset > 0) {
+    for (var i = 0; i < sourceLength; i++) {
+      target[offset + i] = source[i];
+    }
+  }
+  else {
+    for (var i = 0; i < sourceLength; i++) {
+      target[i] = source[i];
+    }
+  }
+}
+
+function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
+  var sourceElementSize = source.BYTES_PER_ELEMENT;
+  var targetElementSize = target.BYTES_PER_ELEMENT;
+  var sourceLength = source.length;
+
+  // Copy left part.
+  function CopyLeftPart() {
+    // First un-mutated byte after the next write
+    var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
+    // Next read at sourcePtr. We do not care for memory changing before
+    // sourcePtr - we have already copied it.
+    var sourcePtr = source.byteOffset;
+    for (var leftIndex = 0;
+         leftIndex < sourceLength && targetPtr <= sourcePtr;
+         leftIndex++) {
+      target[offset + leftIndex] = source[leftIndex];
+      targetPtr += targetElementSize;
+      sourcePtr += sourceElementSize;
+    }
+    return leftIndex;
+  }
+  var leftIndex = CopyLeftPart();
+
+  // Copy rigth part;
+  function CopyRightPart() {
+    // First unmutated byte before the next write
+    var targetPtr =
+      target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
+    // Next read before sourcePtr. We do not care for memory changing after
+    // sourcePtr - we have already copied it.
+    var sourcePtr =
+      source.byteOffset + sourceLength * sourceElementSize;
+    for(var rightIndex = sourceLength - 1;
+        rightIndex >= leftIndex && targetPtr >= sourcePtr;
+        rightIndex--) {
+      target[offset + rightIndex] = source[rightIndex];
+      targetPtr -= targetElementSize;
+      sourcePtr -= sourceElementSize;
+    }
+    return rightIndex;
+  }
+  var rightIndex = CopyRightPart();
+
+  var temp = new $Array(rightIndex + 1 - leftIndex);
+  for (var i = leftIndex; i <= rightIndex; i++) {
+    temp[i - leftIndex] = source[i];
+  }
+  for (i = leftIndex; i <= rightIndex; i++) {
+    target[offset + i] = temp[i - leftIndex];
+  }
+}
+
 function TypedArraySet(obj, offset) {
   var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
   if (intOffset < 0) {
     throw MakeTypeError("typed_array_set_negative_offset");
   }
-  if (%TypedArraySetFastCases(this, obj, intOffset))
-    return;
-
-  var l = obj.length;
-  if (IS_UNDEFINED(l)) {
-    if (IS_NUMBER(obj)) {
-        // For number as a first argument, throw TypeError
-        // instead of silently ignoring the call, so that
-        // the user knows (s)he did something wrong.
-        // (Consistent with Firefox and Blink/WebKit)
-        throw MakeTypeError("invalid_argument");
-    }
-    return;
-  }
-  if (intOffset + l > this.length) {
-    throw MakeRangeError("typed_array_set_source_too_large");
-  }
-  for (var i = 0; i < l; i++) {
-    this[intOffset + i] = obj[i];
+  switch (%TypedArraySetFastCases(this, obj, intOffset)) {
+    // These numbers should be synchronized with runtime.cc.
+    case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
+      return;
+    case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
+      TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
+      return;
+    case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
+      TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
+      return;
+    case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
+      var l = obj.length;
+      if (IS_UNDEFINED(l)) {
+        if (IS_NUMBER(obj)) {
+            // For number as a first argument, throw TypeError
+            // instead of silently ignoring the call, so that
+            // the user knows (s)he did something wrong.
+            // (Consistent with Firefox and Blink/WebKit)
+            throw MakeTypeError("invalid_argument");
+        }
+        return;
+      }
+      if (intOffset + l > this.length) {
+        throw MakeRangeError("typed_array_set_source_too_large");
+      }
+      TypedArraySetFromArrayLike(this, obj, l, intOffset);
+      return;
   }
 }
 
index 4220d21..727c104 100644 (file)
@@ -404,8 +404,6 @@ 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());
@@ -419,16 +417,6 @@ 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;
index cfec0c0..93f3efb 100644 (file)
@@ -271,7 +271,12 @@ void V8::InitializeOncePerProcessImpl() {
     FLAG_gc_global = true;
     FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
   }
-  if (FLAG_trace_hydrogen) FLAG_parallel_recompilation = false;
+
+  if (FLAG_parallel_recompilation &&
+      (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs)) {
+    FLAG_parallel_recompilation = false;
+    PrintF("Parallel recompilation has been disabled for tracing.\n");
+  }
 
   if (FLAG_sweeper_threads <= 0) {
     if (FLAG_concurrent_sweeping) {
index 2111181..e9f1dff 100644 (file)
@@ -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      11
-#define PATCH_LEVEL       0
+#define BUILD_NUMBER      14
+#define PATCH_LEVEL       1
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
index ae9aeee..826c06e 100644 (file)
@@ -373,13 +373,14 @@ void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
 
 bool RelocInfo::IsPatchedReturnSequence() {
   // The recognized call sequence is:
-  //  movq(kScratchRegister, immediate64); call(kScratchRegister);
+  //  movq(kScratchRegister, address); 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_[2 + kPointerSize] != 0xCC;
+  return pc_[Assembler::kMoveAddressIntoScratchRegisterInstructionLength] !=
+         0xCC;
 #else
   return false;
 #endif
index f5939c3..8969d89 100644 (file)
@@ -164,10 +164,7 @@ 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) {
-  // 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;
+  int code_size = Assembler::kCallSequenceLength + guard_bytes;
 
   // Create a code patcher.
   CodePatcher patcher(pc_, code_size);
@@ -183,7 +180,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(kCallCodeSize,
+  ASSERT_EQ(Assembler::kCallSequenceLength,
             patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 
   // Add the requested number of int3 instructions after the call.
index 07afc12..4e36b6e 100644 (file)
@@ -579,29 +579,36 @@ 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.
-  // Distance between the start of the JS return sequence 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 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;
+  // The length of call(kScratchRegister).
+  static const int kCallScratchRegisterInstructionLength = 3;
+  // The length of call(Immediate32).
   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;
+  // 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;
 
   // One byte opcode for test eax,0xXXXXXXXX.
   static const byte kTestEaxByte = 0xA9;
index d34e4f7..18a6e56 100644 (file)
@@ -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;
-    __ pop(kScratchRegister);  // Save return address.
+    __ PopReturnAddressTo(kScratchRegister);
     __ push(rdi);
-    __ push(kScratchRegister);  // Restore return address.
+    __ PushReturnAddressFrom(kScratchRegister);
   } 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,
-                    "Unexpected number of pre-allocated property fields.");
+                    kUnexpectedNumberOfPreAllocatedPropertyFields);
         }
         __ 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, "Property allocation count failed.");
+      __ Assert(positive, kPropertyAllocationCountFailed);
 
       // 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.
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
   __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
-  __ push(rcx);
+  __ PushReturnAddressFrom(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("no cases left");
+  __ Abort(kNoCasesLeft);
 }
 
 
@@ -772,9 +772,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
   { Label done;
     __ testq(rax, rax);
     __ j(not_zero, &done);
-    __ pop(rbx);
+    __ PopReturnAddressTo(rbx);
     __ Push(masm->isolate()->factory()->undefined_value());
-    __ push(rbx);
+    __ PushReturnAddressFrom(rbx);
     __ incq(rax);
     __ bind(&done);
   }
@@ -895,9 +895,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ cmpq(rdx, Immediate(1));
     __ j(not_equal, &non_proxy);
 
-    __ pop(rdx);   // return address
+    __ PopReturnAddressTo(rdx);
     __ push(rdi);  // re-add proxy object as additional argument
-    __ push(rdx);
+    __ PushReturnAddressFrom(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, "Unexpected initial map for InternalArray function");
+    __ Check(not_smi, kUnexpectedInitialMapForInternalArrayFunction);
     __ CmpObjectType(rbx, MAP_TYPE, rcx);
-    __ Check(equal, "Unexpected initial map for InternalArray function");
+    __ Check(equal, kUnexpectedInitialMapForInternalArrayFunction);
   }
 
   // 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, "Unexpected initial map for Array function");
+    __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
     __ CmpObjectType(rbx, MAP_TYPE, rcx);
-    __ Check(equal, "Unexpected initial map for Array function");
+    __ Check(equal, kUnexpectedInitialMapForArrayFunction);
   }
 
   // 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, "Unexpected String function");
+    __ Assert(equal, kUnexpectedStringFunction);
   }
 
   // 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));
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ lea(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
-  __ push(rcx);
+  __ PushReturnAddressFrom(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, "Unexpected string wrapper instance size");
+    __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
     __ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0));
-    __ Assert(equal, "Unexpected unused properties of string wrapper");
+    __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
   }
   __ 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);
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ lea(rsp, Operand(rsp, kPointerSize));
-  __ push(rcx);
+  __ PushReturnAddressFrom(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.
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
   __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
-  __ push(rcx);
+  __ PushReturnAddressFrom(rcx);
 }
 
 
index 551a716..ad33a8c 100644 (file)
@@ -246,17 +246,6 @@ 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) {
@@ -430,12 +419,12 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
 
   // Create a new closure through the slower runtime call.
   __ bind(&gc);
-  __ pop(rcx);  // Temporarily remove return address.
+  __ PopReturnAddressTo(rcx);
   __ pop(rdx);
   __ push(rsi);
   __ push(rdx);
   __ PushRoot(Heap::kFalseValueRootIndex);
-  __ push(rcx);  // Restore return address.
+  __ PushReturnAddressFrom(rcx);
   __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
 }
 
@@ -511,9 +500,8 @@ 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, message);
+    __ Assert(equal, kExpected0AsASmiSentinel);
   }
   __ movq(rcx, GlobalObjectOperand());
   __ movq(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset));
@@ -695,13 +683,13 @@ void BinaryOpStub::Initialize() {}
 
 
 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ pop(rcx);  // Save return address.
+  __ PopReturnAddressTo(rcx);
   __ push(rdx);
   __ push(rax);
   // Left and right arguments are now on top.
   __ Push(Smi::FromInt(MinorKey()));
 
-  __ push(rcx);  // Push return address.
+  __ PushReturnAddressFrom(rcx);
 
   // Patch the caller to an appropriate specialized stub and return the
   // operation result to the caller of the stub.
@@ -954,7 +942,7 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm,
         // Set the map.
         __ AssertRootValue(heap_number_map,
                            Heap::kHeapNumberMapRootIndex,
-                           "HeapNumberMap register clobbered.");
+                           kHeapNumberMapRegisterClobbered);
         __ movq(FieldOperand(rax, HeapObject::kMapOffset),
                 heap_number_map);
         __ cvtqsi2sd(xmm0, rbx);
@@ -974,8 +962,7 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm,
   }
   // No fall-through from this generated code.
   if (FLAG_debug_code) {
-    __ Abort("Unexpected fall-through in "
-             "BinaryStub_GenerateFloatingPointCode.");
+    __ Abort(kUnexpectedFallThroughInBinaryStubGenerateFloatingPointCode);
   }
 }
 
@@ -984,10 +971,10 @@ static void BinaryOpStub_GenerateRegisterArgsPushUnderReturn(
     MacroAssembler* masm) {
   // Push arguments, but ensure they are under the return address
   // for a tail call.
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ push(rdx);
   __ push(rax);
-  __ push(rcx);
+  __ PushReturnAddressFrom(rcx);
 }
 
 
@@ -2155,10 +2142,10 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
   __ JumpIfNotSmi(value, &miss);
 
   // Prepare tail call to StoreIC_ArrayLength.
-  __ pop(scratch);
+  __ PopReturnAddressTo(scratch);
   __ push(receiver);
   __ push(value);
-  __ push(scratch);  // return address
+  __ PushReturnAddressFrom(scratch);
 
   ExternalReference ref =
       ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
@@ -2224,9 +2211,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);
-  __ pop(rbx);  // Return address.
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);
-  __ push(rbx);
+  __ PushReturnAddressFrom(rbx);
   __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
 }
 
@@ -2616,9 +2603,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   if (FLAG_debug_code) {
     Condition is_smi = masm->CheckSmi(rax);
     __ Check(NegateCondition(is_smi),
-        "Unexpected type for RegExp data, FixedArray expected");
+        kUnexpectedTypeForRegExpDataFixedArrayExpected);
     __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
-    __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
+    __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
   }
 
   // rax: RegExp data (FixedArray)
@@ -2984,7 +2971,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, "external string expected, but not found");
+    __ Assert(zero, kExternalStringExpectedButNotFound);
   }
   __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
   // Move the pointer so that offset-wise, it looks like a sequential string.
@@ -3448,7 +3435,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
   }
 
 #ifdef DEBUG
-  __ Abort("Unexpected fall-through from string comparison");
+  __ Abort(kUnexpectedFallThroughFromStringComparison);
 #endif
 
   __ bind(&check_unequal_objects);
@@ -3486,7 +3473,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
   }
 
   // Push arguments below the return address to prepare jump to builtin.
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ push(rdx);
   __ push(rax);
 
@@ -3499,8 +3486,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
     __ Push(Smi::FromInt(NegativeComparisonResult(cc)));
   }
 
-  // Restore return address on the stack.
-  __ push(rcx);
+  __ PushReturnAddressFrom(rcx);
 
   // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
   // tagged as a small integer.
@@ -3669,9 +3655,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
   // Check for function proxy.
   __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
   __ j(not_equal, &non_function);
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ push(rdi);  // put proxy as additional argument under return address
-  __ push(rcx);
+  __ PushReturnAddressFrom(rcx);
   __ Set(rax, argc_ + 1);
   __ Set(rbx, 0);
   __ SetCallKind(rcx, CALL_AS_METHOD);
@@ -4275,7 +4261,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     if (FLAG_debug_code) {
       __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
       __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (check).");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck);
     }
     __ movq(kScratchRegister,
             Operand(kScratchRegister, kOffsetToMapCheckValue));
@@ -4317,7 +4303,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     if (FLAG_debug_code) {
       __ movl(rax, Immediate(kWordBeforeResultValue));
       __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (mov).");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
     }
     __ Set(rax, 0);
   }
@@ -4340,7 +4326,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
     if (FLAG_debug_code) {
       __ movl(rax, Immediate(kWordBeforeResultValue));
       __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
-      __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
+      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
     }
   }
   __ ret(2 * kPointerSize + extra_stack_space);
@@ -4349,9 +4335,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
   __ bind(&slow);
   if (HasCallSiteInlineCheck()) {
     // Remove extra value from the stack.
-    __ pop(rcx);
+    __ PopReturnAddressTo(rcx);
     __ pop(rax);
-    __ push(rcx);
+    __ PushReturnAddressFrom(rcx);
   }
   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
 }
@@ -4404,7 +4390,7 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharCodeAtGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
 
   Factory* factory = masm->isolate()->factory();
   // Index is not a smi.
@@ -4454,7 +4440,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharCodeAt slow case");
+  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
 }
 
 
@@ -4480,7 +4466,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
 void StringCharFromCodeGenerator::GenerateSlow(
     MacroAssembler* masm,
     const RuntimeCallHelper& call_helper) {
-  __ Abort("Unexpected fallthrough to CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
 
   __ bind(&slow_case_);
   call_helper.BeforeCall(masm);
@@ -4492,7 +4478,7 @@ void StringCharFromCodeGenerator::GenerateSlow(
   call_helper.AfterCall(masm);
   __ jmp(&exit_);
 
-  __ Abort("Unexpected fallthrough from CharFromCode slow case");
+  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
 }
 
 
@@ -4822,10 +4808,10 @@ void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
 
 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
                                             Register temp) {
-  __ pop(temp);
+  __ PopReturnAddressTo(temp);
   __ pop(rdx);
   __ pop(rax);
-  __ push(temp);
+  __ PushReturnAddressFrom(temp);
 }
 
 
@@ -5040,7 +5026,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
     if (FLAG_debug_code) {
       __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
       __ cmpq(kScratchRegister, candidate);
-      __ Assert(equal, "oddball in string table is not undefined or the hole");
+      __ Assert(equal, kOddballInStringTableIsNotUndefinedOrTheHole);
     }
     __ jmp(&next_probe[i]);
 
@@ -5529,9 +5515,9 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
   // Inline comparison of ASCII strings.
   __ IncrementCounter(counters->string_compare_native(), 1);
   // Drop arguments from the stack
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ addq(rsp, Immediate(2 * kPointerSize));
-  __ push(rcx);
+  __ PushReturnAddressFrom(rcx);
   GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
 
   // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
@@ -5800,10 +5786,10 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
 
   // Handle more complex cases in runtime.
   __ bind(&runtime);
-  __ pop(tmp1);  // Return address.
+  __ PopReturnAddressTo(tmp1);
   __ push(left);
   __ push(right);
-  __ push(tmp1);
+  __ PushReturnAddressFrom(tmp1);
   if (equality) {
     __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
   } else {
@@ -6411,16 +6397,14 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
   // the runtime.
 
   __ bind(&slow_elements);
-  __ pop(rdi);  // Pop return address and remember to put back later for tail
-                // call.
+  __ PopReturnAddressTo(rdi);
   __ push(rbx);
   __ push(rcx);
   __ push(rax);
   __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
   __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
   __ push(rdx);
-  __ push(rdi);  // Return return address so that tail call returns to right
-                 // place.
+  __ PushReturnAddressFrom(rdi);
   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
 
   // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
@@ -6467,7 +6451,7 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
       StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
   __ movq(rbx, MemOperand(rbp, parameter_count_offset));
   masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
       ? kPointerSize
       : 0;
@@ -6539,7 +6523,7 @@ static void CreateArrayDispatch(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -6602,7 +6586,7 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
   }
 
   // If we reached this point there is a problem.
-  __ Abort("Unexpected ElementsKind in array constructor");
+  __ Abort(kUnexpectedElementsKindInArrayConstructor);
 }
 
 
@@ -6668,9 +6652,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, "Unexpected initial map for Array function");
+    __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
     __ CmpObjectType(rcx, MAP_TYPE, rcx);
-    __ Check(equal, "Unexpected initial map for Array function");
+    __ Check(equal, kUnexpectedInitialMapForArrayFunction);
 
     // We should either have undefined in rbx or a valid cell
     Label okay_here;
@@ -6678,7 +6662,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ Cmp(rbx, undefined_sentinel);
     __ j(equal, &okay_here);
     __ Cmp(FieldOperand(rbx, 0), cell_map);
-    __ Assert(equal, "Expected property cell in register rbx");
+    __ Assert(equal, kExpectedPropertyCellInRegisterRbx);
     __ bind(&okay_here);
   }
 
@@ -6783,9 +6767,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, "Unexpected initial map for Array function");
+    __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
     __ CmpObjectType(rcx, MAP_TYPE, rcx);
-    __ Check(equal, "Unexpected initial map for Array function");
+    __ Check(equal, kUnexpectedInitialMapForArrayFunction);
   }
 
   // Figure out the right elements kind
@@ -6804,7 +6788,7 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ j(equal, &done);
     __ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS));
     __ Assert(equal,
-              "Invalid ElementsKind for InternalArray or InternalPackedArray");
+              kInvalidElementsKindForInternalArrayOrInternalPackedArray);
     __ bind(&done);
   }
 
index a823bf2..a39f14b 100644 (file)
@@ -394,7 +394,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
 
   if (FLAG_debug_code) {
     __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
-    __ Assert(equal, "object found in smi-only array");
+    __ Assert(equal, kObjectFoundInSmiOnlyArray);
   }
 
   __ 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, "external string expected, but not found");
+    __ Assert(zero, kExternalStringExpectedButNotFound);
   }
   // Rule out short external strings.
   STATIC_CHECK(kShortExternalStringTag != 0);
index a337b0d..e6bc929 100644 (file)
@@ -48,11 +48,10 @@ 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::kCallInstructionLength);
+  ASSERT(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength);
   rinfo()->PatchCodeWithCall(
       Isolate::Current()->debug()->debug_break_return()->entry(),
-      Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
+      Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength);
 }
 
 
@@ -82,7 +81,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
   ASSERT(IsDebugBreakSlot());
   rinfo()->PatchCodeWithCall(
       Isolate::Current()->debug()->debug_break_slot()->entry(),
-      Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
+      Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength);
 }
 
 
index b45e966..e9cf567 100644 (file)
@@ -42,7 +42,7 @@ const int Deoptimizer::table_entry_size_ = 10;
 
 
 int Deoptimizer::patch_size() {
-  return Assembler::kCallInstructionLength;
+  return Assembler::kCallSequenceLength;
 }
 
 
@@ -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::kCallInstructionLength);
+    CodePatcher patcher(call_address, Assembler::kCallSequenceLength);
     patcher.masm()->Call(GetDeoptimizationEntry(isolate, i, LAZY),
                          RelocInfo::NONE64);
     ASSERT(prev_call_address == NULL ||
index a24ab53..2af5a81 100644 (file)
@@ -126,6 +126,12 @@ inline Object* JavaScriptFrame::function_slot_object() const {
   return Memory::Object_at(fp() + offset);
 }
 
+
+inline void StackHandler::SetFp(Address slot, Address fp) {
+  Memory::Address_at(slot) = fp;
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_X64_FRAMES_X64_H_
index bac4e79..6333e87 100644 (file)
@@ -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, "Declaration in with context.");
+    __ Check(not_equal, kDeclarationInWithContext);
     __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
-    __ Check(not_equal, "Declaration in catch context.");
+    __ Check(not_equal, kDeclarationInCatchContext);
   }
 }
 
@@ -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("Generator failed to resume.");
+  __ Abort(kGeneratorFailedToResume);
 
   // 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, "Let binding re-initialization.");
+        __ Check(equal, kLetBindingReInitialization);
       }
       // 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), "Non-smi index");
-  __ Check(masm()->CheckSmi(value), "Non-smi value");
+  __ Check(masm()->CheckSmi(index), kNonSmiIndex);
+  __ Check(masm()->CheckSmi(value), kNonSmiValue);
 
   __ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
-  __ Check(less, "Index is too large");
+  __ Check(less, kIndexIsTooLarge);
 
   __ SmiCompare(index, Smi::FromInt(0));
-  __ Check(greater_equal, "Index is negative");
+  __ Check(greater_equal, kIndexIsNegative);
 
   __ 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, "Unexpected string type");
+  __ Check(equal, kUnexpectedStringType);
   __ 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("Attempt to use undefined cache.");
+    __ Abort(kAttemptToUseUndefinedCache);
     __ 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, "No empty arrays here in EmitFastAsciiArrayJoin");
+    __ Assert(below, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
   }
   __ bind(&loop);
   __ movq(string, FieldOperand(elements,
@@ -4335,35 +4335,12 @@ 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());
@@ -4819,7 +4796,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)
-  __ pop(rdx);
+  __ PopReturnAddressTo(rdx);
   __ Move(rcx, masm_->CodeObject());
   __ subq(rdx, rcx);
   __ Integer32ToSmi(rdx, rdx);
index 6e238c7..4837b9a 100644 (file)
@@ -570,10 +570,10 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
   __ j(not_zero, &slow);
 
   // Everything is fine, call runtime.
-  __ pop(rcx);
+  __ PopReturnAddressTo(rcx);
   __ push(rdx);  // receiver
   __ push(rax);  // key
-  __ push(rcx);  // return address
+  __ PushReturnAddressFrom(rcx);
 
   // 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);
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rax);  // receiver
   __ push(rcx);  // name
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -1388,10 +1388,10 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   //  -- rsp[0] : return address
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rax);  // receiver
   __ push(rcx);  // name
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // 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);
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rax);  // name
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // 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
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rax);  // name
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // Perform tail call to the entry.
   __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
@@ -1468,11 +1468,11 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
   //  -- rsp[0] : return address
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rcx);  // name
   __ push(rax);  // value
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -1512,13 +1512,13 @@ void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
   //  -- rdx    : receiver
   //  -- rsp[0] : return address
   // -----------------------------------
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);
   __ push(rcx);
   __ push(rax);
   __ Push(Smi::FromInt(NONE));  // PropertyAttributes
   __ Push(Smi::FromInt(strict_mode));
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // Do tail-call to runtime routine.
   __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
@@ -1534,13 +1534,13 @@ void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
   //  -- rsp[0] : return address
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
   __ Push(Smi::FromInt(NONE));          // PropertyAttributes
   __ Push(Smi::FromInt(strict_mode));   // Strict mode.
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // Do tail-call to runtime routine.
   __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
@@ -1555,11 +1555,11 @@ void StoreIC::GenerateSlow(MacroAssembler* masm) {
   //  -- rsp[0] : return address
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // 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
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // 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
   // -----------------------------------
 
-  __ pop(rbx);
+  __ PopReturnAddressTo(rbx);
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
-  __ push(rbx);  // return address
+  __ PushReturnAddressFrom(rbx);
 
   // Do tail-call to runtime routine.
   ExternalReference ref = miss_mode == MISS_FORCE_GENERIC
index e9210a9..d4c125b 100644 (file)
@@ -96,7 +96,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
 }
 
 
-void LChunkBuilder::Abort(const char* reason) {
+void LChunkBuilder::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -120,6 +120,16 @@ void LCodeGen::Comment(const char* format, ...) {
 }
 
 
+#ifdef _MSC_VER
+void LCodeGen::MakeSureStackPagesMapped(int offset) {
+  const int kPageSize = 4 * KB;
+  for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
+    __ movq(Operand(rsp, offset), rax);
+  }
+}
+#endif
+
+
 bool LCodeGen::GeneratePrologue() {
   ASSERT(is_generating());
 
@@ -169,6 +179,9 @@ bool LCodeGen::GeneratePrologue() {
   if (slots > 0) {
     if (FLAG_debug_code) {
       __ subq(rsp, Immediate(slots * kPointerSize));
+#ifdef _MSC_VER
+      MakeSureStackPagesMapped(slots * kPointerSize);
+#endif
       __ push(rax);
       __ Set(rax, slots);
       __ movq(kScratchRegister, kSlotsZapValue, RelocInfo::NONE64);
@@ -182,15 +195,7 @@ bool LCodeGen::GeneratePrologue() {
     } else {
       __ subq(rsp, Immediate(slots * kPointerSize));
 #ifdef _MSC_VER
-      // On windows, you may not access the stack more than one page below
-      // the most recently mapped page. To make the allocated area randomly
-      // accessible, we write to each page in turn (the value is irrelevant).
-      const int kPageSize = 4 * KB;
-      for (int offset = slots * kPointerSize - kPageSize;
-           offset > 0;
-           offset -= kPageSize) {
-        __ movq(Operand(rsp, offset), rax);
-      }
+      MakeSureStackPagesMapped(slots * kPointerSize);
 #endif
     }
 
@@ -656,7 +661,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
   Address entry =
       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
   if (entry == NULL) {
-    Abort("bailout was not prepared");
+    Abort(kBailoutWasNotPrepared);
     return;
   }
 
@@ -1265,7 +1270,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
   bool can_overflow =
       instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   if (right->IsConstantOperand()) {
-    int right_value = ToInteger32(LConstantOperand::cast(right));
+    int32_t right_value = ToInteger32(LConstantOperand::cast(right));
     if (right_value == -1) {
       __ negl(left);
     } else if (right_value == 0) {
@@ -1357,7 +1362,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
   ASSERT(left->IsRegister());
 
   if (right->IsConstantOperand()) {
-    int right_operand = ToInteger32(LConstantOperand::cast(right));
+    int32_t right_operand = ToInteger32(LConstantOperand::cast(right));
     switch (instr->op()) {
       case Token::BIT_AND:
         __ andl(ToRegister(left), Immediate(right_operand));
@@ -1366,7 +1371,11 @@ void LCodeGen::DoBitI(LBitI* instr) {
         __ orl(ToRegister(left), Immediate(right_operand));
         break;
       case Token::BIT_XOR:
-        __ xorl(ToRegister(left), Immediate(right_operand));
+        if (right_operand == int32_t(~0)) {
+          __ not_(ToRegister(left));
+        } else {
+          __ xorl(ToRegister(left), Immediate(right_operand));
+        }
         break;
       default:
         UNREACHABLE();
@@ -1437,7 +1446,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
         break;
     }
   } else {
-    int value = ToInteger32(LConstantOperand::cast(right));
+    int32_t value = ToInteger32(LConstantOperand::cast(right));
     uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
     switch (instr->op()) {
       case Token::ROR:
@@ -1637,7 +1646,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, "Unexpected string type");
+    __ Check(equal, kUnexpectedStringType);
     __ pop(value);
   }
 
@@ -1651,13 +1660,6 @@ 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);
@@ -2563,7 +2565,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;
-    __ pop(return_addr_reg);
+    __ PopReturnAddressTo(return_addr_reg);
     __ shl(reg, Immediate(kPointerSizeLog2));
     __ addq(rsp, reg);
     __ jmp(return_addr_reg);
@@ -2634,16 +2636,6 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
 }
 
 
-void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) {
-  Register object = ToRegister(instr->object());
-  ExternalReference sites_list_address = instr->GetReference(isolate());
-  __ Load(kScratchRegister, sites_list_address);
-  __ movq(FieldOperand(object, instr->hydrogen()->store_field().offset()),
-          kScratchRegister);
-  __ Store(sites_list_address, object);
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -2780,9 +2772,6 @@ static bool CompactEmit(SmallMapList* list,
                         int i,
                         Isolate* isolate) {
   Handle<Map> map = list->at(i);
-  // If the map has ElementsKind transitions, we will generate map checks
-  // for each kind in __ CompareMap(..., ALLOW_ELEMENTS_TRANSITION_MAPS).
-  if (map->HasElementsTransition()) return false;
   LookupResult lookup(isolate);
   map->LookupDescriptor(NULL, *name, &lookup);
   return lookup.IsField() || lookup.IsConstant();
@@ -2906,8 +2895,8 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
 
   if (instr->length()->IsConstantOperand() &&
       instr->index()->IsConstantOperand()) {
-    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
-    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
+    int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length()));
     int index = (const_length - const_index) + 1;
     __ movq(result, Operand(arguments, index * kPointerSize));
   } else {
@@ -3094,9 +3083,9 @@ Operand LCodeGen::BuildFastArrayOperand(
   Register elements_pointer_reg = ToRegister(elements_pointer);
   int shift_size = ElementsKindToShiftSize(elements_kind);
   if (key->IsConstantOperand()) {
-    int constant_value = ToInteger32(LConstantOperand::cast(key));
+    int32_t constant_value = ToInteger32(LConstantOperand::cast(key));
     if (constant_value & 0xF0000000) {
-      Abort("array index constant value too big");
+      Abort(kArrayIndexConstantValueTooBig);
     }
     return Operand(elements_pointer_reg,
                    ((constant_value + additional_index) << shift_size)
@@ -3434,6 +3423,17 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
 }
 
 
+void LCodeGen::EmitInteger64MathAbs(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 {
@@ -3459,6 +3459,8 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
     __ andpd(input_reg, scratch);
   } else if (r.IsInteger32()) {
     EmitIntegerMathAbs(instr);
+  } else if (r.IsSmi()) {
+    EmitInteger64MathAbs(instr);
   } else {  // Tagged case.
     DeferredMathAbsTaggedHeapNumber* deferred =
         new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
@@ -3955,6 +3957,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   int offset = access.offset();
 
   if (access.IsExternalMemory()) {
+    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
     Register value = ToRegister(instr->value());
     if (instr->object()->IsConstantOperand()) {
       ASSERT(value.is(rax));
@@ -4090,7 +4093,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
       __ AssertZeroExtended(reg);
     }
     if (instr->index()->IsConstantOperand()) {
-      int constant_index =
+      int32_t constant_index =
           ToInteger32(LConstantOperand::cast(instr->index()));
       if (instr->hydrogen()->length()->representation().IsSmi()) {
         __ Cmp(reg, Smi::FromInt(constant_index));
@@ -4107,7 +4110,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
   } else {
     Operand length = ToOperand(instr->length());
     if (instr->index()->IsConstantOperand()) {
-      int constant_index =
+      int32_t constant_index =
           ToInteger32(LConstantOperand::cast(instr->index()));
       if (instr->hydrogen()->length()->representation().IsSmi()) {
         __ Cmp(length, Smi::FromInt(constant_index));
@@ -4394,7 +4397,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
   // DoStringCharCodeAt above.
   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   if (instr->index()->IsConstantOperand()) {
-    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
     __ Push(Smi::FromInt(const_index));
   } else {
     Register index = ToRegister(instr->index());
@@ -4457,13 +4460,6 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
 }
 
 
-void LCodeGen::DoStringLength(LStringLength* instr) {
-  Register string = ToRegister(instr->string());
-  Register result = ToRegister(instr->result());
-  __ movq(result, FieldOperand(string, String::kLengthOffset));
-}
-
-
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
   LOperand* input = instr->value();
   ASSERT(input->IsRegister() || input->IsStackSlot());
@@ -4975,31 +4971,64 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
 }
 
 
-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::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::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);
 
-  Label success;
   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;
   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();
-  DoCheckMapCommon(reg, map, instr);
+  __ CompareMap(reg, map, &success);
+  if (instr->hydrogen()->has_migration_target()) {
+    __ j(not_equal, deferred->entry());
+  } else {
+    DeoptimizeIf(not_equal, instr->environment());
+  }
+
   __ bind(&success);
 }
 
@@ -5053,22 +5082,6 @@ 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:
@@ -5091,10 +5104,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
   }
 
@@ -5146,10 +5161,12 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
     __ Push(Smi::FromInt(size));
   }
 
-  if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
-  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
+    ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
     CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
   } else {
     CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
index 4eab56c..e134229 100644 (file)
@@ -102,7 +102,6 @@ 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,8 +131,7 @@ class LCodeGen BASE_EMBEDDED {
   void DoDeferredAllocate(LAllocate* instr);
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
-
-  void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
+  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
 
 // Parallel move support.
   void DoParallelMove(LParallelMove* move);
@@ -179,7 +177,7 @@ class LCodeGen BASE_EMBEDDED {
 
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
   void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
@@ -268,6 +266,7 @@ class LCodeGen BASE_EMBEDDED {
       uint32_t additional_index = 0);
 
   void EmitIntegerMathAbs(LMathAbs* instr);
+  void EmitInteger64MathAbs(LMathAbs* instr);
 
   // Support for recording safepoint and position information.
   void RecordSafepoint(LPointerMap* pointers,
@@ -345,6 +344,13 @@ class LCodeGen BASE_EMBEDDED {
   void DoStoreKeyedExternalArray(LStoreKeyed* instr);
   void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
   void DoStoreKeyedFixedArray(LStoreKeyed* instr);
+#ifdef _MSC_VER
+  // On windows, you may not access the stack more than one page below
+  // the most recently mapped page. To make the allocated area randomly
+  // accessible, we write an arbitrary value to each page in range
+  // rsp + offset - page_size .. rsp in turn.
+  void MakeSureStackPagesMapped(int offset);
+#endif
 
   Zone* zone_;
   LPlatformChunk* const chunk_;
index 4153417..913e170 100644 (file)
@@ -275,24 +275,6 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) {
 }
 
 
-ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) {
-  switch (hydrogen()->known_list()) {
-    case HLinkObjectInList::ALLOCATION_SITE_LIST:
-      return ExternalReference::allocation_sites_list_address(isolate);
-  }
-
-  UNREACHABLE();
-  // Return a dummy value
-  return ExternalReference::isolate_address(isolate);
-}
-
-
-void LLinkObjectInList::PrintDataTo(StringStream* stream) {
-  object()->PrintTo(stream);
-  stream->Add(" offset %d", hydrogen()->store_field().offset());
-}
-
-
 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
   context()->PrintTo(stream);
   stream->Add("[%d]", slot_index());
@@ -461,7 +443,7 @@ LPlatformChunk* LChunkBuilder::Build() {
 }
 
 
-void LCodeGen::Abort(const char* reason) {
+void LCodeGen::Abort(BailoutReason reason) {
   info()->set_bailout_reason(reason);
   status_ = ABORTED;
 }
@@ -672,7 +654,7 @@ LUnallocated* LChunkBuilder::TempRegister() {
       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
   int vreg = allocator_->GetVirtualRegister();
   if (!allocator_->AllocationOk()) {
-    Abort("Out of virtual registers while trying to allocate temp register.");
+    Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
     vreg = 0;
   }
   operand->set_virtual_register(vreg);
@@ -1339,16 +1321,6 @@ 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);
@@ -1763,17 +1735,6 @@ 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());
@@ -1938,15 +1899,6 @@ 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));
@@ -1955,10 +1907,16 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
 
 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
   LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value());
+  if (!instr->CanOmitMapChecks()) {
+    value = UseRegisterAtStart(instr->value());
+    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
+  }
   LCheckMaps* result = new(zone()) LCheckMaps(value);
-  if (instr->CanOmitMapChecks()) return result;
-  return AssignEnvironment(result);
+  if (!instr->CanOmitMapChecks()) {
+    AssignEnvironment(result);
+    if (instr->has_migration_target()) return AssignPointerMap(result);
+  }
+  return result;
 }
 
 
@@ -2042,13 +2000,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) {
-  LOperand* object = UseRegister(instr->value());
-  LLinkObjectInList* result = new(zone()) LLinkObjectInList(object);
-  return result;
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
@@ -2258,7 +2209,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->transition().is_null() &&
+  bool needs_write_barrier_for_map = instr->has_transition() &&
       instr->NeedsWriteBarrierForMap();
 
   LOperand* obj;
@@ -2345,12 +2296,6 @@ LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
-  LOperand* string = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   info()->MarkAsDeferredCalling();
   LOperand* size = instr->size()->IsConstant()
@@ -2399,7 +2344,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("Too many spill slots needed for OSR");
+    Abort(kTooManySpillSlotsNeededForOSR);
     spill_index = 0;
   }
   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
index cb3a2b0..c3b9db4 100644 (file)
@@ -50,7 +50,6 @@ class LCodeGen;
   V(ArithmeticD)                                \
   V(ArithmeticT)                                \
   V(BitI)                                       \
-  V(BitNotI)                                    \
   V(BoundsCheck)                                \
   V(Branch)                                     \
   V(CallConstantFunction)                       \
@@ -68,7 +67,6 @@ class LCodeGen;
   V(CheckMaps)                                  \
   V(CheckMapValue)                              \
   V(CheckNonSmi)                                \
-  V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
@@ -119,7 +117,6 @@ class LCodeGen;
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
   V(LazyBailout)                                \
-  V(LinkObjectInList)                           \
   V(LoadContextSlot)                            \
   V(LoadExternalArrayPointer)                   \
   V(LoadFieldByIndex)                           \
@@ -174,7 +171,6 @@ class LCodeGen;
   V(StringCharCodeAt)                           \
   V(StringCharFromCode)                         \
   V(StringCompareAndBranch)                     \
-  V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
   V(ThisFunction)                               \
@@ -1314,18 +1310,6 @@ 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) {
@@ -1613,23 +1597,6 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> {
 };
 
 
-class LLinkObjectInList: public LTemplateInstruction<0, 1, 0> {
- public:
-  explicit LLinkObjectInList(LOperand* object) {
-    inputs_[0] = object;
-  }
-
-  LOperand* object() { return inputs_[0]; }
-
-  ExternalReference GetReference(Isolate* isolate);
-
-  DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list")
-  DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList)
-
-  virtual void PrintDataTo(StringStream* stream);
-};
-
-
 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
@@ -2085,7 +2052,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
 
   virtual void PrintDataTo(StringStream* stream);
 
-  Handle<Map> transition() const { return hydrogen()->transition(); }
+  Handle<Map> transition() const { return hydrogen()->transition_map(); }
   Representation representation() const {
     return hydrogen()->field_representation();
   }
@@ -2242,19 +2209,6 @@ class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
 };
 
 
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LStringLength(LOperand* string) {
-    inputs_[0] = string;
-  }
-
-  LOperand* string() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
-  DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
 class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckFunction(LOperand* value) {
@@ -2294,24 +2248,6 @@ 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) {
@@ -2605,7 +2541,7 @@ class LChunkBuilder BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  void Abort(const char* reason);
+  void Abort(BailoutReason reason);
 
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
index 13d7dda..9c9b162 100644 (file)
@@ -155,7 +155,7 @@ int MacroAssembler::LoadAddressSize(ExternalReference source) {
     }
   }
   // Size of movq(destination, src);
-  return 10;
+  return Assembler::kMoveAddressIntoScratchRegisterInstructionLength;
 }
 
 
@@ -449,8 +449,8 @@ void MacroAssembler::RecordWrite(Register object,
 }
 
 
-void MacroAssembler::Assert(Condition cc, const char* msg) {
-  if (emit_debug_code()) Check(cc, msg);
+void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
+  if (emit_debug_code()) Check(cc, reason);
 }
 
 
@@ -466,16 +466,16 @@ void MacroAssembler::AssertFastElements(Register elements) {
     CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
                 Heap::kFixedCOWArrayMapRootIndex);
     j(equal, &ok, Label::kNear);
-    Abort("JSObject with fast elements map has slow elements");
+    Abort(kJSObjectWithFastElementsMapHasSlowElements);
     bind(&ok);
   }
 }
 
 
-void MacroAssembler::Check(Condition cc, const char* msg) {
+void MacroAssembler::Check(Condition cc, BailoutReason reason) {
   Label L;
   j(cc, &L, Label::kNear);
-  Abort(msg);
+  Abort(reason);
   // Control will not return here.
   bind(&L);
 }
@@ -508,12 +508,13 @@ void MacroAssembler::NegativeZeroTest(Register result,
 }
 
 
-void MacroAssembler::Abort(const char* msg) {
+void MacroAssembler::Abort(BailoutReason reason) {
   // 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.
@@ -838,7 +839,7 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
   CompareRoot(return_value, Heap::kNullValueRootIndex);
   j(equal, &ok, Label::kNear);
 
-  Abort("API call returned invalid object");
+  Abort(kAPICallReturnedInvalidObject);
 
   bind(&ok);
 #endif
@@ -1038,7 +1039,7 @@ void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
          RelocInfo::NONE64);
     cmpq(dst, kSmiConstantRegister);
     if (allow_stub_calls()) {
-      Assert(equal, "Uninitialized kSmiConstantRegister");
+      Assert(equal, kUninitializedKSmiConstantRegister);
     } else {
       Label ok;
       j(equal, &ok, Label::kNear);
@@ -1106,7 +1107,7 @@ void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
     Label ok;
     j(zero, &ok, Label::kNear);
     if (allow_stub_calls()) {
-      Abort("Integer32ToSmiField writing to non-smi location");
+      Abort(kInteger32ToSmiFieldWritingToNonSmiLocation);
     } else {
       int3();
     }
@@ -1689,12 +1690,12 @@ void MacroAssembler::SmiAdd(Register dst,
     if (emit_debug_code()) {
       movq(kScratchRegister, src1);
       addq(kScratchRegister, src2);
-      Check(no_overflow, "Smi addition overflow");
+      Check(no_overflow, kSmiAdditionOverflow);
     }
     lea(dst, Operand(src1, src2, times_1, 0));
   } else {
     addq(dst, src2);
-    Assert(no_overflow, "Smi addition overflow");
+    Assert(no_overflow, kSmiAdditionOverflow);
   }
 }
 
@@ -1726,7 +1727,7 @@ void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
     movq(dst, src1);
   }
   subq(dst, src2);
-  Assert(no_overflow, "Smi subtraction overflow");
+  Assert(no_overflow, kSmiSubtractionOverflow);
 }
 
 
@@ -1758,7 +1759,7 @@ void MacroAssembler::SmiSub(Register dst,
     movq(dst, src1);
   }
   subq(dst, src2);
-  Assert(no_overflow, "Smi subtraction overflow");
+  Assert(no_overflow, kSmiSubtractionOverflow);
 }
 
 
@@ -2155,7 +2156,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, "Both registers were smis in SelectNonSmi.");
+    Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi);
   }
 #endif
   STATIC_ASSERT(kSmiTag == 0);
@@ -2510,8 +2511,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).
-  const int kCallInstructionSize = 3;
-  return LoadAddressSize(ext) + kCallInstructionSize;
+  return LoadAddressSize(ext) +
+         Assembler::kCallScratchRegisterInstructionLength;
 }
 
 
@@ -2798,9 +2799,9 @@ void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
   if (is_uint16(bytes_dropped)) {
     ret(bytes_dropped);
   } else {
-    pop(scratch);
+    PopReturnAddressTo(scratch);
     addq(rsp, Immediate(bytes_dropped));
-    push(scratch);
+    PushReturnAddressFrom(scratch);
     ret(0);
   }
 }
@@ -2984,7 +2985,7 @@ void MacroAssembler::LoadUint32(XMMRegister dst,
                                 XMMRegister scratch) {
   if (FLAG_debug_code) {
     cmpq(src, Immediate(0xffffffff));
-    Assert(below_equal, "input GPR is expected to have upper32 cleared");
+    Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared);
   }
   cvtqsi2sd(dst, src);
 }
@@ -3033,7 +3034,7 @@ void MacroAssembler::AssertNumber(Register object) {
     j(is_smi, &ok, Label::kNear);
     Cmp(FieldOperand(object, HeapObject::kMapOffset),
         isolate()->factory()->heap_number_map());
-    Check(equal, "Operand is not a number");
+    Check(equal, kOperandIsNotANumber);
     bind(&ok);
   }
 }
@@ -3042,7 +3043,7 @@ void MacroAssembler::AssertNumber(Register object) {
 void MacroAssembler::AssertNotSmi(Register object) {
   if (emit_debug_code()) {
     Condition is_smi = CheckSmi(object);
-    Check(NegateCondition(is_smi), "Operand is a smi");
+    Check(NegateCondition(is_smi), kOperandIsASmi);
   }
 }
 
@@ -3050,7 +3051,7 @@ void MacroAssembler::AssertNotSmi(Register object) {
 void MacroAssembler::AssertSmi(Register object) {
   if (emit_debug_code()) {
     Condition is_smi = CheckSmi(object);
-    Check(is_smi, "Operand is not a smi");
+    Check(is_smi, kOperandIsNotASmi);
   }
 }
 
@@ -3058,7 +3059,7 @@ void MacroAssembler::AssertSmi(Register object) {
 void MacroAssembler::AssertSmi(const Operand& object) {
   if (emit_debug_code()) {
     Condition is_smi = CheckSmi(object);
-    Check(is_smi, "Operand is not a smi");
+    Check(is_smi, kOperandIsNotASmi);
   }
 }
 
@@ -3068,7 +3069,7 @@ void MacroAssembler::AssertZeroExtended(Register int32_register) {
     ASSERT(!int32_register.is(kScratchRegister));
     movq(kScratchRegister, 0x100000000l, RelocInfo::NONE64);
     cmpq(kScratchRegister, int32_register);
-    Check(above_equal, "32 bit value in register is not zero-extended");
+    Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
   }
 }
 
@@ -3076,12 +3077,12 @@ void MacroAssembler::AssertZeroExtended(Register int32_register) {
 void MacroAssembler::AssertString(Register object) {
   if (emit_debug_code()) {
     testb(object, Immediate(kSmiTagMask));
-    Check(not_equal, "Operand is a smi and not a string");
+    Check(not_equal, kOperandIsASmiAndNotAString);
     push(object);
     movq(object, FieldOperand(object, HeapObject::kMapOffset));
     CmpInstanceType(object, FIRST_NONSTRING_TYPE);
     pop(object);
-    Check(below, "Operand is not a string");
+    Check(below, kOperandIsNotAString);
   }
 }
 
@@ -3089,24 +3090,24 @@ void MacroAssembler::AssertString(Register object) {
 void MacroAssembler::AssertName(Register object) {
   if (emit_debug_code()) {
     testb(object, Immediate(kSmiTagMask));
-    Check(not_equal, "Operand is a smi and not a name");
+    Check(not_equal, kOperandIsASmiAndNotAName);
     push(object);
     movq(object, FieldOperand(object, HeapObject::kMapOffset));
     CmpInstanceType(object, LAST_NAME_TYPE);
     pop(object);
-    Check(below_equal, "Operand is not a name");
+    Check(below_equal, kOperandIsNotAName);
   }
 }
 
 
 void MacroAssembler::AssertRootValue(Register src,
                                      Heap::RootListIndex root_value_index,
-                                     const char* message) {
+                                     BailoutReason reason) {
   if (emit_debug_code()) {
     ASSERT(!src.is(kScratchRegister));
     LoadRoot(kScratchRegister, root_value_index);
     cmpq(src, kScratchRegister);
-    Check(equal, message);
+    Check(equal, reason);
   }
 }
 
@@ -3457,7 +3458,7 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) {
          isolate()->factory()->undefined_value(),
          RelocInfo::EMBEDDED_OBJECT);
     cmpq(Operand(rsp, 0), kScratchRegister);
-    Check(not_equal, "code object not properly patched");
+    Check(not_equal, kCodeObjectNotProperlyPatched);
   }
 }
 
@@ -3466,7 +3467,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
   if (emit_debug_code()) {
     Move(kScratchRegister, Smi::FromInt(type));
     cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
-    Check(equal, "stack frame types must match");
+    Check(equal, kStackFrameTypesMustMatch);
   }
   movq(rsp, rbp);
   pop(rbp);
@@ -3567,8 +3568,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles) {
   // from the caller stack.
   lea(rsp, Operand(r15, 1 * kPointerSize));
 
-  // Push the return address to get ready to return.
-  push(rcx);
+  PushReturnAddressFrom(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, "we should not have an empty lexical context");
+    Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
   }
   // 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, "JSGlobalObject::native_context should be a native context.");
+    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   }
 
   // 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, "JSGlobalProxy::context() should not be null.");
+    Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
 
     // 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, "JSGlobalObject::native_context should be a native context.");
+    Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
     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, "Unexpected allocation top");
+    Check(equal, kUnexpectedAllocationTop);
 #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, "Unaligned allocation in new space");
+    Check(zero, kUnalignedAllocationInNewSpace);
   }
 
   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, "Allocation is not double aligned");
+    Check(zero, kAllocationIsNotDoubleAligned);
   }
 
   // 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, "Allocation is not double aligned");
+    Check(zero, kAllocationIsNotDoubleAligned);
   }
 
   // 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, "Undo allocation of non allocated memory");
+  Check(below, kUndoAllocationOfNonAllocatedMemory);
 #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, "Invalid min_length");
+    Assert(greater_equal, kInvalidMinLength);
   }
   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, "Variable resolved to with context.");
+    Check(not_equal, kVariableResolvedToWithContext);
   }
 }
 
@@ -4340,7 +4340,7 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
     CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
     jmp(&ok);
     bind(&fail);
-    Abort("Global functions must have initial map");
+    Abort(kGlobalFunctionsMustHaveInitialMap);
     bind(&ok);
   }
 }
index 9d5d2a3..61abc20 100644 (file)
@@ -823,6 +823,10 @@ 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);
@@ -837,7 +841,7 @@ class MacroAssembler: public Assembler {
 
   // The size of the code generated for different call instructions.
   int CallSize(Address destination, RelocInfo::Mode rmode) {
-    return kCallInstructionLength;
+    return kCallSequenceLength;
   }
   int CallSize(ExternalReference ext);
   int CallSize(Handle<Code> code_object) {
@@ -1002,7 +1006,7 @@ class MacroAssembler: public Assembler {
   // enabled via --debug-code.
   void AssertRootValue(Register src,
                        Heap::RootListIndex root_value_index,
-                       const char* message);
+                       BailoutReason reason);
 
   // ---------------------------------------------------------------------------
   // Exception handling
@@ -1319,15 +1323,15 @@ class MacroAssembler: public Assembler {
 
   // Calls Abort(msg) if the condition cc is not satisfied.
   // Use --debug_code to enable.
-  void Assert(Condition cc, const char* msg);
+  void Assert(Condition cc, BailoutReason reason);
 
   void AssertFastElements(Register elements);
 
   // Like Assert(), but always enabled.
-  void Check(Condition cc, const char* msg);
+  void Check(Condition cc, BailoutReason reason);
 
   // Print a message to stdout and abort execution.
-  void Abort(const char* msg);
+  void Abort(BailoutReason msg);
 
   // Check that the stack is aligned.
   void CheckStackAlignment();
@@ -1518,6 +1522,10 @@ inline Operand StackSpaceOperand(int index) {
 }
 
 
+inline Operand StackOperandForReturnAddress(int32_t disp) {
+  return Operand(rsp, disp);
+}
+
 
 #ifdef GENERATED_CODE_COVERAGE
 extern void LogGeneratedCodeCoverage(const char* file_line);
index 106ffb7..dcd317c 100644 (file)
@@ -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, "Invalid capture referenced");
+  __ Check(greater_equal, kInvalidCaptureReferenced);
 
   // Succeed on empty capture (including non-participating capture)
   __ j(equal, &fallthrough);
index 542018f..7ad250a 100644 (file)
@@ -410,9 +410,9 @@ static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
   //  -- rsp[0] : return address
   //  -- rsp[8] : last argument in the internal frame of the caller
   // -----------------------------------
-  __ movq(scratch, Operand(rsp, 0));
+  __ movq(scratch, StackOperandForReturnAddress(0));
   __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
-  __ movq(Operand(rsp, 0), scratch);
+  __ movq(StackOperandForReturnAddress(0), scratch);
   __ Move(scratch, Smi::FromInt(0));
   for (int i = 1; i <= kFastApiCallArguments; i++) {
      __ movq(Operand(rsp, i * kPointerSize), scratch);
@@ -431,8 +431,9 @@ static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
   //  -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
   //                                          frame.
   // -----------------------------------
-  __ movq(scratch, Operand(rsp, 0));
-  __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
+  __ movq(scratch, StackOperandForReturnAddress(0));
+  __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
+          scratch);
   __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
 }
 
@@ -829,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.
-    __ pop(scratch1);  // Return address.
+    __ PopReturnAddressTo(scratch1);
     __ push(receiver_reg);
     __ Push(transition);
     __ push(value_reg);
-    __ push(scratch1);
+    __ PushReturnAddressFrom(scratch1);
     __ TailCallExternalReference(
         ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
                           masm->isolate()),
@@ -1283,7 +1284,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
     Handle<ExecutableAccessorInfo> callback) {
   // Insert additional parameters into the stack frame above return address.
   ASSERT(!scratch4().is(reg));
-  __ pop(scratch4());  // Get return address to place it below.
+  __ PopReturnAddressTo(scratch4());
 
   __ push(receiver());  // receiver
   __ push(reg);  // holder
@@ -1323,7 +1324,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
 
   ASSERT(!name_arg.is(scratch4()));
   __ movq(name_arg, rsp);
-  __ push(scratch4());  // Restore return address.
+  __ PushReturnAddressFrom(scratch4());
 
   // v8::Arguments::values_ and handler for name.
   const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -1443,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.
-    __ pop(scratch2());  // save old return address
+    __ PopReturnAddressTo(scratch2());
     PushInterceptorArguments(masm(), receiver(), holder_reg,
                              this->name(), interceptor_holder);
-    __ push(scratch2());  // restore old return address
+    __ PushReturnAddressFrom(scratch2());
 
     ExternalReference ref = ExternalReference(
         IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
@@ -2350,8 +2351,9 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
                   name, depth, &miss);
 
   // Move the return address on top of the stack.
-  __ movq(rax, Operand(rsp, kFastApiCallArguments * kPointerSize));
-  __ movq(Operand(rsp, 0 * kPointerSize), rax);
+  __ movq(rax,
+          StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
+  __ movq(StackOperandForReturnAddress(0), rax);
 
   GenerateFastApiCall(masm(), optimization, argc);
 
@@ -2648,12 +2650,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
   HandlerFrontend(object, receiver(), holder, name, &success);
   __ bind(&success);
 
-  __ pop(scratch1());  // remove the return address
+  __ PopReturnAddressTo(scratch1());
   __ push(receiver());
   __ Push(callback);  // callback info
   __ Push(name);
   __ push(value());
-  __ push(scratch1());  // restore return address
+  __ PushReturnAddressFrom(scratch1());
 
   // Do tail-call to the runtime system.
   ExternalReference store_callback_property =
@@ -2715,12 +2717,12 @@ void StoreStubCompiler::GenerateStoreViaSetter(
 Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
     Handle<JSObject> object,
     Handle<Name> name) {
-  __ pop(scratch1());  // remove the return address
+  __ PopReturnAddressTo(scratch1());
   __ push(receiver());
   __ push(this->name());
   __ push(value());
   __ Push(Smi::FromInt(strict_mode()));
-  __ push(scratch1());  // restore return address
+  __ PushReturnAddressFrom(scratch1());
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
@@ -2936,7 +2938,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
     __ j(equal, &miss);
   } else if (FLAG_debug_code) {
     __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
-    __ Check(not_equal, "DontDelete cells can't contain the hole");
+    __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
   }
 
   HandlerFrontendFooter(name, &success, &miss);
index a12ed79..1f14115 100644 (file)
@@ -246,6 +246,11 @@ 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/deps/v8/test/benchmarks/benchmarks.status b/deps/v8/test/benchmarks/benchmarks.status
new file mode 100644 (file)
index 0000000..651b8d7
--- /dev/null
@@ -0,0 +1,29 @@
+# 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.
+
+# Too slow in Debug mode.
+octane/mandreel: PASS, SKIP if $mode == debug
diff --git a/deps/v8/test/benchmarks/testcfg.py b/deps/v8/test/benchmarks/testcfg.py
new file mode 100644 (file)
index 0000000..5fb3f51
--- /dev/null
@@ -0,0 +1,181 @@
+# 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.
+
+
+import os
+import shutil
+import subprocess
+import tarfile
+
+from testrunner.local import testsuite
+from testrunner.objects import testcase
+
+
+class BenchmarksTestSuite(testsuite.TestSuite):
+
+  def __init__(self, name, root):
+    super(BenchmarksTestSuite, self).__init__(name, root)
+    self.testroot = root
+
+  def ListTests(self, context):
+    tests = []
+    for test in [
+        "kraken/ai-astar",
+        "kraken/audio-beat-detection",
+        "kraken/audio-dft",
+        "kraken/audio-fft",
+        "kraken/audio-oscillator",
+        "kraken/imaging-darkroom",
+        "kraken/imaging-desaturate",
+        "kraken/imaging-gaussian-blur",
+        "kraken/json-parse-financial",
+        "kraken/json-stringify-tinderbox",
+        "kraken/stanford-crypto-aes",
+        "kraken/stanford-crypto-ccm",
+        "kraken/stanford-crypto-pbkdf2",
+        "kraken/stanford-crypto-sha256-iterative",
+
+        "octane/box2d",
+        "octane/code-load",
+        "octane/crypto",
+        "octane/deltablue",
+        "octane/earley-boyer",
+        "octane/gbemu",
+        "octane/mandreel",
+        "octane/navier-stokes",
+        "octane/pdfjs",
+        "octane/raytrace",
+        "octane/regexp",
+        "octane/richards",
+        "octane/splay",
+
+        "sunspider/3d-cube",
+        "sunspider/3d-morph",
+        "sunspider/3d-raytrace",
+        "sunspider/access-binary-trees",
+        "sunspider/access-fannkuch",
+        "sunspider/access-nbody",
+        "sunspider/access-nsieve",
+        "sunspider/bitops-3bit-bits-in-byte",
+        "sunspider/bitops-bits-in-byte",
+        "sunspider/bitops-bitwise-and",
+        "sunspider/bitops-nsieve-bits",
+        "sunspider/controlflow-recursive",
+        "sunspider/crypto-aes",
+        "sunspider/crypto-md5",
+        "sunspider/crypto-sha1",
+        "sunspider/date-format-tofte",
+        "sunspider/date-format-xparb",
+        "sunspider/math-cordic",
+        "sunspider/math-partial-sums",
+        "sunspider/math-spectral-norm",
+        "sunspider/regexp-dna",
+        "sunspider/string-base64",
+        "sunspider/string-fasta",
+        "sunspider/string-tagcloud",
+        "sunspider/string-unpack-code",
+        "sunspider/string-validate-input"]:
+      tests.append(testcase.TestCase(self, test))
+    return tests
+
+  def GetFlagsForTestCase(self, testcase, context):
+    result = []
+    result += context.mode_flags
+    if testcase.path.startswith("kraken"):
+      result.append(os.path.join(self.testroot, "%s-data.js" % testcase.path))
+      result.append(os.path.join(self.testroot, "%s.js" % testcase.path))
+    elif testcase.path.startswith("octane"):
+      result.append(os.path.join(self.testroot, "octane/base.js"))
+      result.append(os.path.join(self.testroot, "%s.js" % testcase.path))
+      result += ["-e", "BenchmarkSuite.RunSuites({});"]
+    elif testcase.path.startswith("sunspider"):
+      result.append(os.path.join(self.testroot, "%s.js" % testcase.path))
+    return testcase.flags + result
+
+  def GetSourceForTest(self, testcase):
+    filename = os.path.join(self.testroot, testcase.path + ".js")
+    with open(filename) as f:
+      return f.read()
+
+  def _DownloadIfNecessary(self, url, revision, target_dir):
+    # Maybe we're still up to date?
+    revision_file = "CHECKED_OUT_%s" % target_dir
+    checked_out_revision = None
+    if os.path.exists(revision_file):
+      with open(revision_file) as f:
+        checked_out_revision = f.read()
+    if checked_out_revision == revision:
+      return
+
+    # If we have a local archive file with the test data, extract it.
+    if os.path.exists(target_dir):
+      shutil.rmtree(target_dir)
+    archive_file = "downloaded_%s_%s.tar.gz" % (target_dir, revision)
+    if os.path.exists(archive_file):
+      with tarfile.open(archive_file, "r:gz") as tar:
+        tar.extractall()
+      with open(revision_file, "w") as f:
+        f.write(revision)
+      return
+
+    # No cached copy. Check out via SVN, and pack as .tar.gz for later use.
+    command = "svn co %s -r %s %s" % (url, revision, target_dir)
+    code = subprocess.call(command, shell=True)
+    if code != 0:
+      raise Exception("Error checking out %s benchmark" % target_dir)
+    with tarfile.open(archive_file, "w:gz") as tar:
+      tar.add("%s" % target_dir)
+    with open(revision_file, "w") as f:
+      f.write(revision)
+
+  def DownloadData(self):
+    old_cwd = os.getcwd()
+    os.chdir(os.path.abspath(self.root))
+
+    self._DownloadIfNecessary(
+        ("http://svn.webkit.org/repository/webkit/trunk/PerformanceTests/"
+         "SunSpider/tests/sunspider-1.0/"),
+        "153700", "sunspider")
+
+    self._DownloadIfNecessary(
+        ("http://kraken-mirror.googlecode.com/svn/trunk/kraken/tests/"
+         "kraken-1.1/"),
+        "8", "kraken")
+
+    self._DownloadIfNecessary(
+        "http://octane-benchmark.googlecode.com/svn/trunk/",
+        "22", "octane")
+
+    os.chdir(old_cwd)
+
+  def VariantFlags(self):
+    # Both --nocrankshaft and --stressopt are very slow.
+    return [[]]
+
+
+def GetSuite(name, root):
+  return BenchmarksTestSuite(name, root)
index 94dcce1..a2caf0f 100644 (file)
@@ -99,9 +99,10 @@ v8::Isolate* CcTest::default_isolate_;
 
 
 class CcTestArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
- public:
   virtual void* Allocate(size_t length) { return malloc(length); }
-  virtual void Free(void* data) { free(data); }
+  virtual void Free(void* data, size_t length) { free(data); }
+  // TODO(dslomov): Remove when v8:2823 is fixed.
+  virtual void Free(void* data) { UNREACHABLE(); }
 };
 
 
index 193126a..1282d7d 100644 (file)
@@ -300,4 +300,57 @@ static inline void SimulateFullSpace(v8::internal::PagedSpace* space) {
 }
 
 
+// Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry
+class RandomNumberGenerator {
+ public:
+  RandomNumberGenerator() {
+    init();
+  }
+
+  void init(uint32_t seed = 0x5688c73e) {
+    static const uint32_t phi = 0x9e3779b9;
+    c = 362436;
+    i = kQSize-1;
+    Q[0] = seed;
+    Q[1] = seed + phi;
+    Q[2] = seed + phi + phi;
+    for (unsigned j = 3; j < kQSize; j++) {
+      Q[j] = Q[j - 3] ^ Q[j - 2] ^ phi ^ j;
+    }
+  }
+
+  uint32_t next() {
+    uint64_t a = 18782;
+    uint32_t r = 0xfffffffe;
+    i = (i + 1) & (kQSize-1);
+    uint64_t t = a * Q[i] + c;
+    c = (t >> 32);
+    uint32_t x = static_cast<uint32_t>(t + c);
+    if (x < c) {
+      x++;
+      c++;
+    }
+    return (Q[i] = r - x);
+  }
+
+  uint32_t next(int max) {
+    return next() % max;
+  }
+
+  bool next(double threshold) {
+    ASSERT(threshold >= 0.0 && threshold <= 1.0);
+    if (threshold == 1.0) return true;
+    if (threshold == 0.0) return false;
+    uint32_t value = next() % 100000;
+    return threshold > static_cast<double>(value)/100000.0;
+  }
+
+ private:
+  static const uint32_t kQSize = 4096;
+  uint32_t Q[kQSize];
+  uint32_t c;
+  uint32_t i;
+};
+
+
 #endif  // ifndef CCTEST_H_
index 3c6f85e..664f905 100644 (file)
@@ -3565,6 +3565,7 @@ static void check_message_0(v8::Handle<v8::Message> message,
   CHECK_EQ(5.76, data->NumberValue());
   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
+  CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }
 
@@ -3591,6 +3592,7 @@ static void check_message_1(v8::Handle<v8::Message> message,
                             v8::Handle<Value> data) {
   CHECK(data->IsNumber());
   CHECK_EQ(1337, data->Int32Value());
+  CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }
 
@@ -3615,6 +3617,7 @@ static void check_message_2(v8::Handle<v8::Message> message,
   v8::Local<v8::Value> hidden_property =
       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
   CHECK(v8_str("hidden value")->Equals(hidden_property));
+  CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }
 
@@ -3636,6 +3639,112 @@ TEST(MessageHandler2) {
 }
 
 
+static void check_message_3(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+TEST(MessageHandler3) {
+  message_received = false;
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message_3);
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::True());
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_3);
+}
+
+
+static void check_message_4(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(!message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+TEST(MessageHandler4) {
+  message_received = false;
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message_4);
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::False());
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_4);
+}
+
+
+static void check_message_5a(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+static void check_message_5b(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(!message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+TEST(MessageHandler5) {
+  message_received = false;
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message_5a);
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::True());
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_5a);
+
+  message_received = false;
+  v8::V8::AddMessageListener(check_message_5b);
+  origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::False());
+  script = Script::Compile(v8_str("throw 'error'"),
+                           &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_5b);
+}
+
+
 THREADED_TEST(GetSetProperty) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
@@ -4279,7 +4388,7 @@ TEST(APIThrowMessageOverwrittenToString) {
 }
 
 
-static void check_custom_error_message(
+static void check_custom_error_tostring(
     v8::Handle<v8::Message> message,
     v8::Handle<v8::Value> data) {
   const char* uncaught_error = "Uncaught MyError toString";
@@ -4290,7 +4399,7 @@ static void check_custom_error_message(
 TEST(CustomErrorToString) {
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
-  v8::V8::AddMessageListener(check_custom_error_message);
+  v8::V8::AddMessageListener(check_custom_error_tostring);
   CompileRun(
     "function MyError(name, message) {                   "
     "  this.name = name;                                 "
@@ -4301,6 +4410,58 @@ TEST(CustomErrorToString) {
     "  return 'MyError toString';                        "
     "};                                                  "
     "throw new MyError('my name', 'my message');         ");
+  v8::V8::RemoveMessageListeners(check_custom_error_tostring);
+}
+
+
+static void check_custom_error_message(
+    v8::Handle<v8::Message> message,
+    v8::Handle<v8::Value> data) {
+  const char* uncaught_error = "Uncaught MyError: my message";
+  printf("%s\n", *v8::String::Utf8Value(message->Get()));
+  CHECK(message->Get()->Equals(v8_str(uncaught_error)));
+}
+
+
+TEST(CustomErrorMessage) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  v8::V8::AddMessageListener(check_custom_error_message);
+
+  // Handlebars.
+  CompileRun(
+    "function MyError(msg) {                             "
+    "  this.name = 'MyError';                            "
+    "  this.message = msg;                               "
+    "}                                                   "
+    "MyError.prototype = new Error();                    "
+    "throw new MyError('my message');                    ");
+
+  // Closure.
+  CompileRun(
+    "function MyError(msg) {                             "
+    "  this.name = 'MyError';                            "
+    "  this.message = msg;                               "
+    "}                                                   "
+    "inherits = function(childCtor, parentCtor) {        "
+    "    function tempCtor() {};                         "
+    "    tempCtor.prototype = parentCtor.prototype;      "
+    "    childCtor.superClass_ = parentCtor.prototype;   "
+    "    childCtor.prototype = new tempCtor();           "
+    "    childCtor.prototype.constructor = childCtor;    "
+    "};                                                  "
+    "inherits(MyError, Error);                           "
+    "throw new MyError('my message');                    ");
+
+  // Object.create.
+  CompileRun(
+    "function MyError(msg) {                             "
+    "  this.name = 'MyError';                            "
+    "  this.message = msg;                               "
+    "}                                                   "
+    "MyError.prototype = Object.create(Error.prototype); "
+    "throw new MyError('my message');                    ");
+
   v8::V8::RemoveMessageListeners(check_custom_error_message);
 }
 
@@ -19754,6 +19915,16 @@ THREADED_TEST(Regress260106) {
 }
 
 
+THREADED_TEST(JSONParse) {
+  LocalContext context;
+  HandleScope scope(context->GetIsolate());
+  Local<Object> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
+  Handle<Object> global = context->Global();
+  global->Set(v8_str("obj"), obj);
+  ExpectString("JSON.stringify(obj)", "{\"x\":42}");
+}
+
+
 #ifndef WIN32
 class ThreadInterruptTest {
  public:
index cb677b3..cac162e 100644 (file)
@@ -1418,4 +1418,25 @@ TEST(16) {
   CHECK_EQ(0x11121313, t.dst4);
 }
 
+
+TEST(17) {
+  // Test generating labels at high addresses.
+  // Should not assert.
+  CcTest::InitializeVM();
+  Isolate* isolate = Isolate::Current();
+  HandleScope scope(isolate);
+
+  // Generate a code segment that will be longer than 2^24 bytes.
+  Assembler assm(isolate, NULL, 0);
+  for (size_t i = 0; i < 1 << 23 ; ++i) {  // 2^23
+    __ nop();
+  }
+
+  Label target;
+  __ b(eq, &target);
+  __ bind(&target);
+  __ nop();
+}
+
+
 #undef __
index 6f8de60..a3c0b54 100644 (file)
@@ -94,7 +94,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
     Register reg = Register::from_code(reg_num);
     if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
       __ cmp(reg, MemOperand(esp, 0));
-      __ Assert(equal, "register was clobbered");
+      __ Assert(equal, kRegisterWasClobbered);
       __ add(esp, Immediate(kPointerSize));
     }
   }
index e30c160..0bffb87 100644 (file)
@@ -93,7 +93,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
     Register reg = Register::from_code(reg_num);
     if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
       __ cmpq(reg, MemOperand(rsp, 0));
-      __ Assert(equal, "register was clobbered");
+      __ Assert(equal, kRegisterWasClobbered);
       __ addq(rsp, Immediate(kPointerSize));
     }
   }
index bed8a6c..b5ba46c 100644 (file)
@@ -105,6 +105,7 @@ static Handle<JSFunction> Compile(const char* source) {
                         Handle<String>(),
                         0,
                         0,
+                        false,
                         Handle<Context>(isolate->native_context()),
                         NULL,
                         NULL,
index d9ecc41..daf8db6 100644 (file)
@@ -410,6 +410,21 @@ TEST(GetProfilerWhenIsolateIsNotInitialized) {
 }
 
 
+TEST(ProfileStartEndTime) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+
+  int64_t time_before_profiling = i::OS::Ticks();
+  v8::Local<v8::String> profile_name = v8::String::New("test");
+  cpu_profiler->StartCpuProfiling(profile_name);
+  const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
+  CHECK(time_before_profiling <= profile->GetStartTime());
+  CHECK(profile->GetStartTime() <= profile->GetEndTime());
+  CHECK(profile->GetEndTime() <= i::OS::Ticks());
+}
+
+
 static const v8::CpuProfile* RunProfiler(
     LocalContext& env, v8::Handle<v8::Function> function,
     v8::Handle<v8::Value> argv[], int argc,
index a274d75..ea11dbc 100644 (file)
@@ -25,6 +25,9 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include <map>
+#include <vector>
+
 #include "global-handles.h"
 
 #include "cctest.h"
@@ -315,3 +318,204 @@ TEST(ImplicitReferences) {
   ASSERT(implicit_refs->at(1)->length == 1);
   ASSERT(implicit_refs->at(1)->children[0] == g2c1.location());
 }
+
+
+static const int kBlockSize = 256;
+
+
+TEST(BlockCollection) {
+  v8::V8::Initialize();
+  Isolate* isolate = Isolate::Current();
+  GlobalHandles* global_handles = isolate->global_handles();
+  CHECK_EQ(0, global_handles->block_count());
+  CHECK_EQ(0, global_handles->global_handles_count());
+  Object* object = isolate->heap()->undefined_value();
+  const int kNumberOfBlocks = 5;
+  typedef Handle<Object> Block[kBlockSize];
+  for (int round = 0; round < 3; round++) {
+    Block blocks[kNumberOfBlocks];
+    for (int i = 0; i < kNumberOfBlocks; i++) {
+      for (int j = 0; j < kBlockSize; j++) {
+        blocks[i][j] = global_handles->Create(object);
+      }
+    }
+    CHECK_EQ(kNumberOfBlocks, global_handles->block_count());
+    for (int i = 0; i < kNumberOfBlocks; i++) {
+      for (int j = 0; j < kBlockSize; j++) {
+        global_handles->Destroy(blocks[i][j].location());
+      }
+    }
+    isolate->heap()->CollectAllAvailableGarbage("BlockCollection");
+    CHECK_EQ(0, global_handles->global_handles_count());
+    CHECK_EQ(1, global_handles->block_count());
+  }
+}
+
+
+class RandomMutationData {
+ public:
+  explicit RandomMutationData(Isolate* isolate)
+      : isolate_(isolate), weak_offset_(0) {}
+
+  void Mutate(double strong_growth_tendency,
+              double weak_growth_tendency = 0.05) {
+    for (int i = 0; i < kBlockSize * 100; i++) {
+      if (rng_.next(strong_growth_tendency)) {
+        AddStrong();
+      } else if (strong_nodes_.size() != 0) {
+        size_t to_remove = rng_.next(static_cast<int>(strong_nodes_.size()));
+        RemoveStrong(to_remove);
+      }
+      if (rng_.next(weak_growth_tendency)) AddWeak();
+      if (rng_.next(0.05)) {
+#ifdef DEBUG
+        isolate_->global_handles()->VerifyBlockInvariants();
+#endif
+      }
+      if (rng_.next(0.0001)) {
+        isolate_->heap()->PerformScavenge();
+      } else if (rng_.next(0.00003)) {
+        isolate_->heap()->CollectAllAvailableGarbage();
+      }
+      CheckSizes();
+    }
+  }
+
+  void RemoveAll() {
+    while (strong_nodes_.size() != 0) {
+      RemoveStrong(strong_nodes_.size() - 1);
+    }
+    isolate_->heap()->PerformScavenge();
+    isolate_->heap()->CollectAllAvailableGarbage();
+    CheckSizes();
+  }
+
+ private:
+  typedef std::vector<Object**> NodeVector;
+  typedef std::map<int32_t, Object**> NodeMap;
+
+  void CheckSizes() {
+    int stored_sizes =
+        static_cast<int>(strong_nodes_.size() + weak_nodes_.size());
+    CHECK_EQ(isolate_->global_handles()->global_handles_count(), stored_sizes);
+  }
+
+  void AddStrong() {
+    Object* object = isolate_->heap()->undefined_value();
+    Object** location = isolate_->global_handles()->Create(object).location();
+    strong_nodes_.push_back(location);
+  }
+
+  void RemoveStrong(size_t offset) {
+    isolate_->global_handles()->Destroy(strong_nodes_.at(offset));
+    strong_nodes_.erase(strong_nodes_.begin() + offset);
+  }
+
+  void AddWeak() {
+    v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
+    v8::HandleScope scope(isolate);
+    v8::Local<v8::Object> object = v8::Object::New();
+    int32_t offset = ++weak_offset_;
+    object->Set(7, v8::Integer::New(offset, isolate));
+    v8::Persistent<v8::Object> persistent(isolate, object);
+    persistent.MakeWeak(isolate, this, WeakCallback);
+    persistent.MarkIndependent();
+    Object** location = v8::Utils::OpenPersistent(persistent).location();
+    bool inserted =
+        weak_nodes_.insert(std::make_pair(offset, location)).second;
+    CHECK(inserted);
+  }
+
+  static void WeakCallback(v8::Isolate* isolate,
+                           v8::Persistent<v8::Object>* persistent,
+                           RandomMutationData* data) {
+    v8::Local<v8::Object> object =
+        v8::Local<v8::Object>::New(isolate, *persistent);
+    int32_t offset =
+        v8::Local<v8::Integer>::Cast(object->Get(7))->Int32Value();
+    Object** location = v8::Utils::OpenPersistent(persistent).location();
+    NodeMap& weak_nodes = data->weak_nodes_;
+    NodeMap::iterator it = weak_nodes.find(offset);
+    CHECK(it != weak_nodes.end());
+    CHECK(it->second == location);
+    weak_nodes.erase(it);
+    persistent->Dispose();
+  }
+
+  Isolate* isolate_;
+  RandomNumberGenerator rng_;
+  NodeVector strong_nodes_;
+  NodeMap weak_nodes_;
+  int32_t weak_offset_;
+};
+
+
+TEST(RandomMutation) {
+  v8::V8::Initialize();
+  Isolate* isolate = Isolate::Current();
+  CHECK_EQ(0, isolate->global_handles()->block_count());
+  HandleScope handle_scope(isolate);
+  v8::Context::Scope context_scope(
+      v8::Context::New(reinterpret_cast<v8::Isolate*>(isolate)));
+  RandomMutationData data(isolate);
+  // grow some
+  data.Mutate(0.65);
+  data.Mutate(0.55);
+  // balanced mutation
+  for (int i = 0; i < 3; i++) data.Mutate(0.50);
+  // shrink some
+  data.Mutate(0.45);
+  data.Mutate(0.35);
+  // clear everything
+  data.RemoveAll();
+}
+
+
+TEST(EternalHandles) {
+  CcTest::InitializeVM();
+  Isolate* isolate = Isolate::Current();
+  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
+  EternalHandles* eternals = isolate->eternal_handles();
+
+  // Create a number of handles that will not be on a block boundary
+  const int kArrayLength = 2048-1;
+  int indices[kArrayLength];
+
+  CHECK_EQ(0, eternals->NumberOfHandles());
+  for (int i = 0; i < kArrayLength; i++) {
+    HandleScope scope(isolate);
+    v8::Local<v8::Object> object = v8::Object::New();
+    object->Set(i, v8::Integer::New(i, v8_isolate));
+    if (i % 2 == 0) {
+      // Create with internal api
+      indices[i] = eternals->Create(isolate, *v8::Utils::OpenHandle(*object));
+    } else {
+      // Create with external api
+      indices[i] = object.Eternalize(v8_isolate);
+    }
+  }
+
+  isolate->heap()->CollectAllAvailableGarbage();
+
+  for (int i = 0; i < kArrayLength; i++) {
+    for (int j = 0; j < 2; j++) {
+      HandleScope scope(isolate);
+      v8::Local<v8::Object> object;
+      if (j == 0) {
+        // Test internal api
+        v8::Local<v8::Value> local =
+            v8::Utils::ToLocal(eternals->Get(indices[i]));
+        object = v8::Handle<v8::Object>::Cast(local);
+      } else {
+        // Test external api
+        object = v8::Local<v8::Object>::GetEternal(v8_isolate, indices[i]);
+      }
+      v8::Local<v8::Value> value = object->Get(i);
+      CHECK(value->IsInt32());
+      CHECK_EQ(i, value->Int32Value());
+    }
+  }
+
+  CHECK_EQ(kArrayLength, eternals->NumberOfHandles());
+}
+
index 6af9962..5f71350 100644 (file)
@@ -960,7 +960,7 @@ TEST(Regression39128) {
   Factory* factory = isolate->factory();
 
   // Increase the chance of 'bump-the-pointer' allocation in old space.
-  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
 
   v8::HandleScope scope(CcTest::isolate());
 
@@ -984,7 +984,7 @@ TEST(Regression39128) {
   // just enough room to allocate JSObject and thus fill the newspace.
 
   int allocation_amount = Min(FixedArray::kMaxSize,
-                              Page::kMaxNonCodeHeapObjectSize);
+                              Page::kMaxNonCodeHeapObjectSize + kPointerSize);
   int allocation_len = LenFromSize(allocation_amount);
   NewSpace* new_space = HEAP->new_space();
   Address* top_addr = new_space->allocation_top_address();
index 310d93c..d6591a0 100644 (file)
 #include "cctest.h"
 #include "zone-inl.h"
 
-// Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry
-class RandomNumberGenerator {
- public:
-  RandomNumberGenerator() {
-    init();
-  }
-
-  void init(uint32_t seed = 0x5688c73e) {
-    static const uint32_t phi = 0x9e3779b9;
-    c = 362436;
-    i = kQSize-1;
-    Q[0] = seed;
-    Q[1] = seed + phi;
-    Q[2] = seed + phi + phi;
-    for (unsigned j = 3; j < kQSize; j++) {
-      Q[j] = Q[j - 3] ^ Q[j - 2] ^ phi ^ j;
-    }
-  }
-
-  uint32_t next() {
-    uint64_t a = 18782;
-    uint32_t r = 0xfffffffe;
-    i = (i + 1) & (kQSize-1);
-    uint64_t t = a * Q[i] + c;
-    c = (t >> 32);
-    uint32_t x = static_cast<uint32_t>(t + c);
-    if (x < c) {
-      x++;
-      c++;
-    }
-    return (Q[i] = r - x);
-  }
-
-  uint32_t next(int max) {
-    return next() % max;
-  }
-
-  bool next(double threshold) {
-    ASSERT(threshold >= 0.0 && threshold <= 1.0);
-    if (threshold == 1.0) return true;
-    if (threshold == 0.0) return false;
-    uint32_t value = next() % 100000;
-    return threshold > static_cast<double>(value)/100000.0;
-  }
-
- private:
-  static const uint32_t kQSize = 4096;
-  uint32_t Q[kQSize];
-  uint32_t c;
-  uint32_t i;
-};
-
 
 using namespace v8::internal;
 
index 39a8857..d8d5aea 100644 (file)
@@ -38,7 +38,7 @@ assertFalse(options.locale === '');
 assertFalse(options.locale === undefined);
 
 // Then check for equality.
-assertEquals(options.locale, getDefaultLocale());
+assertEquals(options.locale, %GetDefaultICULocale());
 
 var iteratorNone = new Intl.v8BreakIterator();
 assertEquals(options.locale, iteratorNone.resolvedOptions().locale);
index 56457b4..5ac8fbc 100644 (file)
@@ -29,4 +29,4 @@
 
 var iterator = Intl.v8BreakIterator(['xx']);
 
-assertEquals(iterator.resolvedOptions().locale, getDefaultLocale());
+assertEquals(iterator.resolvedOptions().locale, %GetDefaultICULocale());
index f6ffba8..db9b1e7 100644 (file)
@@ -38,7 +38,7 @@ assertFalse(options.locale === '');
 assertFalse(options.locale === undefined);
 
 // Then check for equality.
-assertEquals(options.locale, getDefaultLocale());
+assertEquals(options.locale, %GetDefaultICULocale());
 
 var collatorNone = new Intl.Collator();
 assertEquals(options.locale, collatorNone.resolvedOptions().locale);
@@ -48,5 +48,5 @@ var collatorBraket = new Intl.Collator({});
 assertEquals(options.locale, collatorBraket.resolvedOptions().locale);
 
 var collatorWithOptions = new Intl.Collator(undefined, {usage: 'search'});
-assertEquals(getDefaultLocale() + '-u-co-search',
+assertEquals(%GetDefaultICULocale() + '-u-co-search',
              collatorWithOptions.resolvedOptions().locale);
index ea143fd..3963d47 100644 (file)
@@ -29,4 +29,4 @@
 
 var collator = Intl.Collator(['xx']);
 
-assertEquals(collator.resolvedOptions().locale, getDefaultLocale());
+assertEquals(collator.resolvedOptions().locale, %GetDefaultICULocale());
index 2dcb0f8..8e9b7fc 100644 (file)
@@ -38,7 +38,7 @@ assertFalse(options.locale === '');
 assertFalse(options.locale === undefined);
 
 // Then check for equality.
-assertEquals(options.locale, getDefaultLocale());
+assertEquals(options.locale, %GetDefaultICULocale());
 
 var dtfNone = new Intl.DateTimeFormat();
 assertEquals(options.locale, dtfNone.resolvedOptions().locale);
index 8867ec6..6f063ab 100644 (file)
@@ -29,4 +29,4 @@
 
 var dtf = Intl.DateTimeFormat(['xx']);
 
-assertEquals(dtf.resolvedOptions().locale, getDefaultLocale());
+assertEquals(dtf.resolvedOptions().locale, %GetDefaultICULocale());
index 913626b..7ef0abb 100644 (file)
 
 prefix intl
 
-# The following tests use getDefaultLocale() or getDefaultTimezone().
-break-iterator/default-locale: FAIL
-break-iterator/wellformed-unsupported-locale: FAIL
-collator/default-locale: FAIL
-collator/wellformed-unsupported-locale: FAIL
-date-format/default-locale: FAIL
+# The following tests use getDefaultTimeZone().
 date-format/resolved-options: FAIL
 date-format/timezone: FAIL
-date-format/wellformed-unsupported-locale: FAIL
 general/v8Intl-exists: FAIL
-number-format/default-locale: FAIL
-number-format/wellformed-unsupported-locale: FAIL
index 0d5e24d..cd67ba7 100644 (file)
@@ -38,7 +38,7 @@ assertFalse(options.locale === '');
 assertFalse(options.locale === undefined);
 
 // Then check for equality.
-assertEquals(options.locale, getDefaultLocale());
+assertEquals(options.locale, %GetDefaultICULocale());
 
 var nfNone = new Intl.NumberFormat();
 assertEquals(options.locale, nfNone.resolvedOptions().locale);
index e3fe9cc..195eba4 100644 (file)
@@ -29,4 +29,4 @@
 
 var nf = Intl.NumberFormat(['xx']);
 
-assertEquals(nf.resolvedOptions().locale, getDefaultLocale());
+assertEquals(nf.resolvedOptions().locale, %GetDefaultICULocale());
index d25683b..09d29d0 100644 (file)
@@ -52,7 +52,7 @@ class IntlTestSuite(testsuite.TestSuite):
     return tests
 
   def GetFlagsForTestCase(self, testcase, context):
-    flags = [] + context.mode_flags
+    flags = ["--allow-natives-syntax"] + context.mode_flags
 
     files = []
     files.append(os.path.join(self.root, "assert.js"))
diff --git a/deps/v8/test/mjsunit/harmony/array-find.js b/deps/v8/test/mjsunit/harmony/array-find.js
new file mode 100644 (file)
index 0000000..906c9cd
--- /dev/null
@@ -0,0 +1,280 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-arrays
+
+assertEquals(1, Array.prototype.find.length);
+
+var a = [21, 22, 23, 24];
+assertEquals(undefined, a.find(function() { return false; }));
+assertEquals(21, a.find(function() { return true; }));
+assertEquals(undefined, a.find(function(val) { return 121 === val; }));
+assertEquals(24, a.find(function(val) { return 24 === val; }));
+assertEquals(23, a.find(function(val) { return 23 === val; }), null);
+assertEquals(22, a.find(function(val) { return 22 === val; }), undefined);
+
+
+//
+// Test predicate is not called when array is empty
+//
+(function() {
+  var a = [];
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+
+  a.find(function(val, key, obj) {
+    o = obj;
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return false;
+  });
+
+  assertEquals(-1, l);
+  assertEquals(-1, o);
+  assertEquals(-1, v);
+  assertEquals(-1, k);
+})();
+
+
+//
+// Test predicate is called with correct argumetns
+//
+(function() {
+  var a = ["b"];
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+
+  var found = a.find(function(val, key, obj) {
+    o = obj;
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return false;
+  });
+
+  assertArrayEquals(a, o);
+  assertEquals(a.length, l);
+  assertEquals("b", v);
+  assertEquals(0, k);
+  assertEquals(undefined, found);
+})();
+
+
+//
+// Test predicate is called array.length times
+//
+(function() {
+  var a = [1, 2, 3, 4, 5];
+  var l = 0;
+  var found = a.find(function() {
+    l++;
+    return false;
+  });
+
+  assertEquals(a.length, l);
+  assertEquals(undefined, found);
+})();
+
+
+//
+// Test Array.prototype.find works with String
+//
+(function() {
+  var a = "abcd";
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+  var found = Array.prototype.find.call(a, function(val, key, obj) {
+    o = obj.toString();
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return false;
+  });
+
+  assertEquals(a, o);
+  assertEquals(a.length, l);
+  assertEquals("d", v);
+  assertEquals(3, k);
+  assertEquals(undefined, found);
+
+  found = Array.prototype.find.apply(a, [function(val, key, obj) {
+    o = obj.toString();
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return true;
+  }]);
+
+  assertEquals(a, o);
+  assertEquals(a.length, l);
+  assertEquals("a", v);
+  assertEquals(0, k);
+  assertEquals("a", found);
+})();
+
+
+//
+// Test Array.prototype.find works with exotic object
+//
+(function() {
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+  var a = {
+    prop1: "val1",
+    prop2: "val2",
+    isValid: function() {
+      return this.prop1 === "val1" && this.prop2 === "val2";
+    }
+  };
+
+  Array.prototype.push.apply(a, [30, 31, 32]);
+  var found = Array.prototype.find.call(a, function(val, key, obj) {
+    o = obj;
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return !obj.isValid();
+  });
+
+  assertArrayEquals(a, o);
+  assertEquals(3, l);
+  assertEquals(32, v);
+  assertEquals(2, k);
+  assertEquals(undefined, found);
+})();
+
+
+//
+// Test array modifications
+//
+(function() {
+  var a = [1, 2, 3];
+  var found = a.find(function(val) { a.push(val); return false; });
+  assertArrayEquals([1, 2, 3, 1, 2, 3], a);
+  assertEquals(6, a.length);
+  assertEquals(undefined, found);
+
+  a = [1, 2, 3];
+  found = a.find(function(val, key) { a[key] = ++val; return false; });
+  assertArrayEquals([2, 3, 4], a);
+  assertEquals(3, a.length);
+  assertEquals(undefined, found);
+})();
+
+
+//
+// Test predicate is only called for existing elements
+//
+(function() {
+  var a = new Array(30);
+  a[11] = 21;
+  a[7] = 10;
+  a[29] = 31;
+
+  var count = 0;
+  a.find(function() { count++; return false; });
+  assertEquals(3, count);
+})();
+
+
+//
+// Test thisArg
+//
+(function() {
+  // Test String as a thisArg
+  var found = [1, 2, 3].find(function(val, key) {
+    return this.charAt(Number(key)) === String(val);
+  }, "321");
+  assertEquals(2, found);
+
+  // Test object as a thisArg
+  var thisArg = {
+    elementAt: function(key) {
+      return this[key];
+    }
+  };
+  Array.prototype.push.apply(thisArg, ["c", "b", "a"]);
+
+  found = ["a", "b", "c"].find(function(val, key) {
+    return this.elementAt(key) === val;
+  }, thisArg);
+  assertEquals("b", found);
+})();
+
+// Test exceptions
+assertThrows('Array.prototype.find.call(null, function() { })',
+  TypeError);
+assertThrows('Array.prototype.find.call(undefined, function() { })',
+  TypeError);
+assertThrows('Array.prototype.find.apply(null, function() { }, [])',
+  TypeError);
+assertThrows('Array.prototype.find.apply(undefined, function() { }, [])',
+  TypeError);
+
+assertThrows('[].find(null)', TypeError);
+assertThrows('[].find(undefined)', TypeError);
+assertThrows('[].find(0)', TypeError);
+assertThrows('[].find(true)', TypeError);
+assertThrows('[].find(false)', TypeError);
+assertThrows('[].find("")', TypeError);
+assertThrows('[].find({})', TypeError);
+assertThrows('[].find([])', TypeError);
+assertThrows('[].find(/\d+/)', TypeError);
+
+assertThrows('Array.prototype.find.call({}, null)', TypeError);
+assertThrows('Array.prototype.find.call({}, undefined)', TypeError);
+assertThrows('Array.prototype.find.call({}, 0)', TypeError);
+assertThrows('Array.prototype.find.call({}, true)', TypeError);
+assertThrows('Array.prototype.find.call({}, false)', TypeError);
+assertThrows('Array.prototype.find.call({}, "")', TypeError);
+assertThrows('Array.prototype.find.call({}, {})', TypeError);
+assertThrows('Array.prototype.find.call({}, [])', TypeError);
+assertThrows('Array.prototype.find.call({}, /\d+/)', TypeError);
+
+assertThrows('Array.prototype.find.apply({}, null, [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, undefined, [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, 0, [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, true, [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, false, [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, "", [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, {}, [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, [], [])', TypeError);
+assertThrows('Array.prototype.find.apply({}, /\d+/, [])', TypeError);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/harmony/array-findindex.js b/deps/v8/test/mjsunit/harmony/array-findindex.js
new file mode 100644 (file)
index 0000000..928cad7
--- /dev/null
@@ -0,0 +1,280 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-arrays
+
+assertEquals(1, Array.prototype.findIndex.length);
+
+var a = [21, 22, 23, 24];
+assertEquals(-1, a.findIndex(function() { return false; }));
+assertEquals(-1, a.findIndex(function(val) { return 121 === val; }));
+assertEquals(0, a.findIndex(function() { return true; }));
+assertEquals(1, a.findIndex(function(val) { return 22 === val; }), undefined);
+assertEquals(2, a.findIndex(function(val) { return 23 === val; }), null);
+assertEquals(3, a.findIndex(function(val) { return 24 === val; }));
+
+
+//
+// Test predicate is not called when array is empty
+//
+(function() {
+  var a = [];
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+
+  a.findIndex(function(val, key, obj) {
+    o = obj;
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return false;
+  });
+
+  assertEquals(-1, l);
+  assertEquals(-1, o);
+  assertEquals(-1, v);
+  assertEquals(-1, k);
+})();
+
+
+//
+// Test predicate is called with correct argumetns
+//
+(function() {
+  var a = ["b"];
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+
+  var index = a.findIndex(function(val, key, obj) {
+    o = obj;
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return false;
+  });
+
+  assertArrayEquals(a, o);
+  assertEquals(a.length, l);
+  assertEquals("b", v);
+  assertEquals(0, k);
+  assertEquals(-1, index);
+})();
+
+
+//
+// Test predicate is called array.length times
+//
+(function() {
+  var a = [1, 2, 3, 4, 5];
+  var l = 0;
+
+  a.findIndex(function() {
+    l++;
+    return false;
+  });
+
+  assertEquals(a.length, l);
+})();
+
+
+//
+// Test Array.prototype.findIndex works with String
+//
+(function() {
+  var a = "abcd";
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+
+  var index = Array.prototype.findIndex.call(a, function(val, key, obj) {
+    o = obj.toString();
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return false;
+  });
+
+  assertEquals(a, o);
+  assertEquals(a.length, l);
+  assertEquals("d", v);
+  assertEquals(3, k);
+  assertEquals(-1, index);
+
+  index = Array.prototype.findIndex.apply(a, [function(val, key, obj) {
+    o = obj.toString();
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return true;
+  }]);
+
+  assertEquals(a, o);
+  assertEquals(a.length, l);
+  assertEquals("a", v);
+  assertEquals(0, k);
+  assertEquals(0, index);
+})();
+
+
+//
+// Test Array.prototype.findIndex works with exotic object
+//
+(function() {
+  var l = -1;
+  var o = -1;
+  var v = -1;
+  var k = -1;
+  var a = {
+    prop1: "val1",
+    prop2: "val2",
+    isValid: function() {
+      return this.prop1 === "val1" && this.prop2 === "val2";
+    }
+  };
+
+  Array.prototype.push.apply(a, [30, 31, 32]);
+
+  var index = Array.prototype.findIndex.call(a, function(val, key, obj) {
+    o = obj;
+    l = obj.length;
+    v = val;
+    k = key;
+
+    return !obj.isValid();
+  });
+
+  assertArrayEquals(a, o);
+  assertEquals(3, l);
+  assertEquals(32, v);
+  assertEquals(2, k);
+  assertEquals(-1, index);
+})();
+
+
+//
+// Test array modifications
+//
+(function() {
+  var a = [1, 2, 3];
+  a.findIndex(function(val) { a.push(val); return false; });
+  assertArrayEquals([1, 2, 3, 1, 2, 3], a);
+  assertEquals(6, a.length);
+
+  a = [1, 2, 3];
+  a.findIndex(function(val, key) { a[key] = ++val; return false; });
+  assertArrayEquals([2, 3, 4], a);
+  assertEquals(3, a.length);
+})();
+
+
+//
+// Test predicate is only called for existing elements
+//
+(function() {
+  var a = new Array(30);
+  a[11] = 21;
+  a[7] = 10;
+  a[29] = 31;
+
+  var count = 0;
+  a.findIndex(function() { count++; return false; });
+  assertEquals(3, count);
+})();
+
+
+//
+// Test thisArg
+//
+(function() {
+  // Test String as a thisArg
+  var index = [1, 2, 3].findIndex(function(val, key) {
+    return this.charAt(Number(key)) === String(val);
+  }, "321");
+  assertEquals(1, index);
+
+  // Test object as a thisArg
+  var thisArg = {
+    elementAt: function(key) {
+      return this[key];
+    }
+  };
+  Array.prototype.push.apply(thisArg, ["c", "b", "a"]);
+
+  index = ["a", "b", "c"].findIndex(function(val, key) {
+    return this.elementAt(key) === val;
+  }, thisArg);
+  assertEquals(1, index);
+})();
+
+// Test exceptions
+assertThrows('Array.prototype.findIndex.call(null, function() { })',
+  TypeError);
+assertThrows('Array.prototype.findIndex.call(undefined, function() { })',
+  TypeError);
+assertThrows('Array.prototype.findIndex.apply(null, function() { }, [])',
+  TypeError);
+assertThrows('Array.prototype.findIndex.apply(undefined, function() { }, [])',
+  TypeError);
+
+assertThrows('[].findIndex(null)', TypeError);
+assertThrows('[].findIndex(undefined)', TypeError);
+assertThrows('[].findIndex(0)', TypeError);
+assertThrows('[].findIndex(true)', TypeError);
+assertThrows('[].findIndex(false)', TypeError);
+assertThrows('[].findIndex("")', TypeError);
+assertThrows('[].findIndex({})', TypeError);
+assertThrows('[].findIndex([])', TypeError);
+assertThrows('[].findIndex(/\d+/)', TypeError);
+
+assertThrows('Array.prototype.findIndex.call({}, null)', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, undefined)', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, 0)', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, true)', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, false)', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, "")', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, {})', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, [])', TypeError);
+assertThrows('Array.prototype.findIndex.call({}, /\d+/)', TypeError);
+
+assertThrows('Array.prototype.findIndex.apply({}, null, [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, undefined, [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, 0, [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, true, [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, false, [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, "", [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, {}, [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, [], [])', TypeError);
+assertThrows('Array.prototype.findIndex.apply({}, /\d+/, [])', TypeError);
\ No newline at end of file
index f3a2627..6a402e7 100644 (file)
@@ -39,7 +39,7 @@ function TestArrayPrototype() {
 TestArrayPrototype();
 
 function assertIteratorResult(value, done, result) {
-  assertEquals({ value: value, done: done}, result);
+  assertEquals({value: value, done: done}, result);
 }
 
 function TestValues() {
@@ -70,9 +70,9 @@ TestValuesMutate();
 function TestKeys() {
   var array = ['a', 'b', 'c'];
   var iterator = array.keys();
-  assertIteratorResult('0', false, iterator.next());
-  assertIteratorResult('1', false, iterator.next());
-  assertIteratorResult('2', false, iterator.next());
+  assertIteratorResult(0, false, iterator.next());
+  assertIteratorResult(1, false, iterator.next());
+  assertIteratorResult(2, false, iterator.next());
   assertIteratorResult(void 0, true, iterator.next());
 
   array.push('d');
@@ -83,11 +83,11 @@ TestKeys();
 function TestKeysMutate() {
   var array = ['a', 'b', 'c'];
   var iterator = array.keys();
-  assertIteratorResult('0', false, iterator.next());
-  assertIteratorResult('1', false, iterator.next());
-  assertIteratorResult('2', false, iterator.next());
+  assertIteratorResult(0, false, iterator.next());
+  assertIteratorResult(1, false, iterator.next());
+  assertIteratorResult(2, false, iterator.next());
   array.push('d');
-  assertIteratorResult('3', false, iterator.next());
+  assertIteratorResult(3, false, iterator.next());
   assertIteratorResult(void 0, true, iterator.next());
 }
 TestKeysMutate();
@@ -95,9 +95,9 @@ TestKeysMutate();
 function TestEntries() {
   var array = ['a', 'b', 'c'];
   var iterator = array.entries();
-  assertIteratorResult(['0', 'a'], false, iterator.next());
-  assertIteratorResult(['1', 'b'], false, iterator.next());
-  assertIteratorResult(['2', 'c'], false, iterator.next());
+  assertIteratorResult([0, 'a'], false, iterator.next());
+  assertIteratorResult([1, 'b'], false, iterator.next());
+  assertIteratorResult([2, 'c'], false, iterator.next());
   assertIteratorResult(void 0, true, iterator.next());
 
   array.push('d');
@@ -108,11 +108,11 @@ TestEntries();
 function TestEntriesMutate() {
   var array = ['a', 'b', 'c'];
   var iterator = array.entries();
-  assertIteratorResult(['0', 'a'], false, iterator.next());
-  assertIteratorResult(['1', 'b'], false, iterator.next());
-  assertIteratorResult(['2', 'c'], false, iterator.next());
+  assertIteratorResult([0, 'a'], false, iterator.next());
+  assertIteratorResult([1, 'b'], false, iterator.next());
+  assertIteratorResult([2, 'c'], false, iterator.next());
   array.push('d');
-  assertIteratorResult(['3', 'd'], false, iterator.next());
+  assertIteratorResult([3, 'd'], false, iterator.next());
   assertIteratorResult(void 0, true, iterator.next());
 }
 TestEntriesMutate();
@@ -168,7 +168,7 @@ function TestForArrayKeys() {
   assertEquals(8, buffer.length);
 
   for (var i = 0; i < buffer.length; i++) {
-    assertEquals(String(i), buffer[i]);
+    assertEquals(i, buffer[i]);
   }
 }
 TestForArrayKeys();
@@ -189,7 +189,7 @@ function TestForArrayEntries() {
   assertTrue(isNaN(buffer[buffer.length - 1][1]));
 
   for (var i = 0; i < buffer.length; i++) {
-    assertEquals(String(i), buffer[i][0]);
+    assertEquals(i, buffer[i][0]);
   }
 }
 TestForArrayEntries();
index 3e87e6b..174d3d1 100644 (file)
@@ -207,10 +207,10 @@ TestArbitrary(new WeakMap);
 
 
 // Test direct constructor call
-assertTrue(Set() instanceof Set);
-assertTrue(Map() instanceof Map);
-assertTrue(WeakMap() instanceof WeakMap);
-assertTrue(WeakSet() instanceof WeakSet);
+assertThrows(function() { Set(); }, TypeError);
+assertThrows(function() { Map(); }, TypeError);
+assertThrows(function() { WeakMap(); }, TypeError);
+assertThrows(function() { WeakSet(); }, TypeError);
 
 
 // Test whether NaN values as keys are treated correctly.
@@ -308,7 +308,6 @@ TestPrototype(WeakSet);
 function TestConstructor(C) {
   assertFalse(C === Object.prototype.constructor);
   assertSame(C, C.prototype.constructor);
-  assertSame(C, C().__proto__.constructor);
   assertSame(C, (new C).__proto__.constructor);
 }
 TestConstructor(Set);
index 103dda6..06254ee 100644 (file)
@@ -259,6 +259,16 @@ records = undefined;
 Object.deliverChangeRecords(observer.callback);
 observer.assertRecordCount(1);
 
+// Get notifier prior to observing
+reset();
+var obj = {};
+Object.getNotifier(obj);
+Object.observe(obj, observer.callback);
+obj.id = 1;
+Object.deliverChangeRecords(observer.callback);
+observer.assertCallbackRecords([
+  { object: obj, type: 'new', name: 'id' },
+]);
 
 // Observing a continuous stream of changes, while itermittantly unobserving.
 reset();
@@ -636,8 +646,8 @@ function recursiveObserver2(r) {
 Object.observe(obj1, recursiveObserver2);
 Object.observe(obj2, recursiveObserver2);
 ++obj1.a;
-Object.deliverChangeRecords(recursiveObserver2);
 // TODO(verwaest): Disabled because of bug 2774.
+// Object.deliverChangeRecords(recursiveObserver2);
 // assertEquals(199, recordCount);
 
 
@@ -783,6 +793,8 @@ observer.assertNotCalled();
 // Test all kinds of objects generically.
 function TestObserveConfigurable(obj, prop) {
   reset();
+  Object.observe(obj, observer.callback);
+  Object.unobserve(obj, observer.callback);
   obj[prop] = 1;
   Object.observe(obj, observer.callback);
   obj[prop] = 2;
@@ -852,6 +864,8 @@ function TestObserveConfigurable(obj, prop) {
 
 function TestObserveNonConfigurable(obj, prop, desc) {
   reset();
+  Object.observe(obj, observer.callback);
+  Object.unobserve(obj, observer.callback);
   obj[prop] = 1;
   Object.observe(obj, observer.callback);
   obj[prop] = 4;
index c6e7f9f..9e2228a 100644 (file)
@@ -285,8 +285,8 @@ assertEquals(4, wh4.q);
 // http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving_membrane
 
 function createMembrane(wetTarget) {
-  var wet2dry = WeakMap();
-  var dry2wet = WeakMap();
+  var wet2dry = new WeakMap();
+  var dry2wet = new WeakMap();
 
   function asDry(obj) {
     registerObject(obj)
index abfc0f5..789de35 100644 (file)
@@ -51,7 +51,7 @@ function TestSet2(construct, fix, create) {
   var p3 = create(handler)
   fix(p3)
 
-  var s = construct();
+  var s = new construct();
   s.add(p1);
   s.add(p2);
   assertTrue(s.has(p1));
@@ -88,7 +88,7 @@ function TestMap2(construct, fix, create) {
   var p3 = create(handler)
   fix(p3)
 
-  var m = construct();
+  var m = new construct();
   m.set(p1, 123);
   m.set(p2, 321);
   assertTrue(m.has(p1));
diff --git a/deps/v8/test/mjsunit/harmony/string-contains.js b/deps/v8/test/mjsunit/harmony/string-contains.js
new file mode 100644 (file)
index 0000000..700a6ed
--- /dev/null
@@ -0,0 +1,151 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-strings
+
+assertEquals(1, String.prototype.contains.length);
+
+var reString = "asdf[a-z]+(asdf)?";
+assertTrue(reString.contains("[a-z]+"));
+assertTrue(reString.contains("(asdf)?"));
+
+// Random greek letters
+var twoByteString = "\u039a\u0391\u03a3\u03a3\u0395";
+
+// Test single char pattern
+assertTrue(twoByteString.contains("\u039a"), "Lamda");
+assertTrue(twoByteString.contains("\u0391"), "Alpha");
+assertTrue(twoByteString.contains("\u03a3"), "First Sigma");
+assertTrue(twoByteString.contains("\u03a3",3), "Second Sigma");
+assertTrue(twoByteString.contains("\u0395"), "Epsilon");
+assertFalse(twoByteString.contains("\u0392"), "Not beta");
+
+// Test multi-char pattern
+assertTrue(twoByteString.contains("\u039a\u0391"), "lambda Alpha");
+assertTrue(twoByteString.contains("\u0391\u03a3"), "Alpha Sigma");
+assertTrue(twoByteString.contains("\u03a3\u03a3"), "Sigma Sigma");
+assertTrue(twoByteString.contains("\u03a3\u0395"), "Sigma Epsilon");
+
+assertFalse(twoByteString.contains("\u0391\u03a3\u0395"),
+    "Not Alpha Sigma Epsilon");
+
+//single char pattern
+assertTrue(twoByteString.contains("\u0395"));
+
+assertThrows("String.prototype.contains.call(null, 'test')", TypeError);
+assertThrows("String.prototype.contains.call(null, null)", TypeError);
+assertThrows("String.prototype.contains.call(undefined, undefined)", TypeError);
+
+assertThrows("String.prototype.contains.apply(null, ['test'])", TypeError);
+assertThrows("String.prototype.contains.apply(null, [null])", TypeError);
+assertThrows("String.prototype.contains.apply(undefined, [undefined])", TypeError);
+
+var TEST_INPUT = [{
+  msg: "Empty string", val: ""
+}, {
+  msg: "Number 1234.34", val: 1234.34
+}, {
+  msg: "Integer number 0", val: 0
+}, {
+  msg: "Negative number -1", val: -1
+}, {
+  msg: "Boolean true", val: true
+}, {
+  msg: "Boolean false", val: false
+}, {
+  msg: "Regular expression /\d+/", val: /\d+/
+}, {
+  msg: "Empty array []", val: []
+}, {
+  msg: "Empty object {}", val: {}
+}, {
+  msg: "Array of size 3", val: new Array(3)
+}];
+
+var i = 0;
+var l = TEST_INPUT.length;
+
+for (; i < l; i++) {
+  var e = TEST_INPUT[i];
+  var v = e.val;
+  var s = String(v);
+  assertTrue(s.contains(v), e.msg);
+  assertTrue(String.prototype.contains.call(v, v), e.msg);
+  assertTrue(String.prototype.contains.apply(v, [v]), e.msg);
+}
+
+// Test cases found in FF
+assertTrue("abc".contains("a"));
+assertTrue("abc".contains("b"));
+assertTrue("abc".contains("abc"));
+assertTrue("abc".contains("bc"));
+assertFalse("abc".contains("d"));
+assertFalse("abc".contains("abcd"));
+assertFalse("abc".contains("ac"));
+assertTrue("abc".contains("abc", 0));
+assertTrue("abc".contains("bc", 0));
+assertFalse("abc".contains("de", 0));
+assertTrue("abc".contains("bc", 1));
+assertTrue("abc".contains("c", 1));
+assertFalse("abc".contains("a", 1));
+assertFalse("abc".contains("abc", 1));
+assertTrue("abc".contains("c", 2));
+assertFalse("abc".contains("d", 2));
+assertFalse("abc".contains("dcd", 2));
+assertFalse("abc".contains("a", 42));
+assertFalse("abc".contains("a", Infinity));
+assertTrue("abc".contains("ab", -43));
+assertFalse("abc".contains("cd", -42));
+assertTrue("abc".contains("ab", -Infinity));
+assertFalse("abc".contains("cd", -Infinity));
+assertTrue("abc".contains("ab", NaN));
+assertFalse("abc".contains("cd", NaN));
+assertFalse("xyzzy".contains("zy\0", 2));
+
+var dots = Array(10000).join('.');
+assertFalse(dots.contains("\x01", 10000));
+assertFalse(dots.contains("\0", 10000));
+
+var myobj = {
+  toString: function () {
+    return "abc";
+  },
+  contains: String.prototype.contains
+};
+assertTrue(myobj.contains("abc"));
+assertFalse(myobj.contains("cd"));
+
+var gotStr = false;
+var gotPos = false;
+myobj = {
+  toString: function () {
+    assertFalse(gotPos);
+    gotStr = true;
+    return "xyz";
+  },
+  contains: String.prototype.contains
+};
diff --git a/deps/v8/test/mjsunit/harmony/string-endswith.js b/deps/v8/test/mjsunit/harmony/string-endswith.js
new file mode 100644 (file)
index 0000000..128cf1d
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-strings
+
+assertEquals(1, String.prototype.endsWith.length);
+
+var testString = "Hello World";
+assertTrue(testString.endsWith(""));
+assertTrue(testString.endsWith("World"));
+assertFalse(testString.endsWith("world"));
+assertFalse(testString.endsWith("Hello World!"));
+assertFalse(testString.endsWith(null));
+assertFalse(testString.endsWith(undefined));
+
+assertTrue("null".endsWith(null));
+assertTrue("undefined".endsWith(undefined));
+
+var georgianUnicodeString = "\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10D7";
+assertTrue(georgianUnicodeString.endsWith(georgianUnicodeString));
+assertTrue(georgianUnicodeString.endsWith("\u10D4\u10D5\u10D6\u10D7"));
+assertFalse(georgianUnicodeString.endsWith("\u10D0"));
+
+assertThrows("String.prototype.endsWith.call(null, 'test')", TypeError);
+assertThrows("String.prototype.endsWith.call(null, null)", TypeError);
+assertThrows("String.prototype.endsWith.call(undefined, undefined)", TypeError);
+
+assertThrows("String.prototype.endsWith.apply(null, ['test'])", TypeError);
+assertThrows("String.prototype.endsWith.apply(null, [null])", TypeError);
+assertThrows("String.prototype.endsWith.apply(undefined, [undefined])", TypeError);
+
+var TEST_INPUT = [{
+  msg: "Empty string", val: ""
+}, {
+  msg: "Number 1234.34", val: 1234.34
+}, {
+  msg: "Integer number 0", val: 0
+}, {
+  msg: "Negative number -1", val: -1
+}, {
+  msg: "Boolean true", val: true
+}, {
+  msg: "Boolean false", val: false
+}, {
+  msg: "Regular expression /\d+/", val: /\d+/
+}, {
+  msg: "Empty array []", val: []
+}, {
+  msg: "Empty object {}", val: {}
+}, {
+  msg: "Array of size 3", val: new Array(3)
+}];
+
+function testNonStringValues() {
+  var i = 0;
+  var l = TEST_INPUT.length;
+
+  for (; i < l; i++) {
+    var e = TEST_INPUT[i];
+    var v = e.val;
+    var s = String(v);
+    assertTrue(s.endsWith(v), e.msg);
+    assertTrue(String.prototype.endsWith.call(v, v), e.msg);
+    assertTrue(String.prototype.endsWith.apply(v, [v]), e.msg);
+  }
+}
+testNonStringValues();
+
+var CustomType = function(value) {
+  this.endsWith = String.prototype.endsWith;
+  this.toString = function() {
+    return String(value);
+  }
+};
+
+function testCutomType() {
+  var i = 0;
+  var l = TEST_INPUT.length;
+
+  for (; i < l; i++) {
+    var e = TEST_INPUT[i];
+    var v = e.val;
+    var o = new CustomType(v);
+    assertTrue(o.endsWith(v), e.msg);
+  }
+}
+testCutomType();
+
+
+// Test cases found in FF
+assertTrue("abc".endsWith("abc"));
+assertTrue("abcd".endsWith("bcd"));
+assertTrue("abc".endsWith("c"));
+assertFalse("abc".endsWith("abcd"));
+assertFalse("abc".endsWith("bbc"));
+assertFalse("abc".endsWith("b"));
+assertTrue("abc".endsWith("abc", 3));
+assertTrue("abc".endsWith("bc", 3));
+assertFalse("abc".endsWith("a", 3));
+assertTrue("abc".endsWith("bc", 3));
+assertTrue("abc".endsWith("a", 1));
+assertFalse("abc".endsWith("abc", 1));
+assertTrue("abc".endsWith("b", 2));
+assertFalse("abc".endsWith("d", 2));
+assertFalse("abc".endsWith("dcd", 2));
+assertFalse("abc".endsWith("a", 42));
+assertTrue("abc".endsWith("bc", Infinity));
+assertFalse("abc".endsWith("a", Infinity));
+assertTrue("abc".endsWith("bc", undefined));
+assertFalse("abc".endsWith("bc", -43));
+assertFalse("abc".endsWith("bc", -Infinity));
+assertFalse("abc".endsWith("bc", NaN));
diff --git a/deps/v8/test/mjsunit/harmony/string-repeat.js b/deps/v8/test/mjsunit/harmony/string-repeat.js
new file mode 100644 (file)
index 0000000..182e5c0
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-strings
+
+assertEquals("000", String.prototype.repeat.call(0, 3));
+assertEquals("-1-1-1", String.prototype.repeat.call(-1, 3));
+assertEquals("2.12.12.1", String.prototype.repeat.call(2.1, 3));
+assertEquals("", String.prototype.repeat.call([], 3));
+assertEquals("1,2,3", String.prototype.repeat.call([1, 2, 3], 1));
+assertEquals("true", String.prototype.repeat.call(true, 1));
+assertEquals("false", String.prototype.repeat.call(false, 1));
+assertEquals("[object Object]", String.prototype.repeat.call({}, 1));
+
+assertEquals("000", String.prototype.repeat.apply(0, [3]));
+assertEquals("-1-1-1", String.prototype.repeat.apply(-1, [3]));
+assertEquals("2.12.12.1", String.prototype.repeat.apply(2.1, [3]));
+assertEquals("", String.prototype.repeat.apply([], [3]));
+assertEquals("1,2,3", String.prototype.repeat.apply([1, 2, 3], [1]));
+assertEquals("true", String.prototype.repeat.apply(true, [1]));
+assertEquals("false", String.prototype.repeat.apply(false, [1]));
+assertEquals("[object Object]", String.prototype.repeat.apply({}, [1]));
+
+assertEquals("\u10D8\u10D8\u10D8", "\u10D8".repeat(3));
+
+assertThrows('String.prototype.repeat.call(null, 1)', TypeError);
+assertThrows('String.prototype.repeat.call(undefined, 1)', TypeError);
+assertThrows('String.prototype.repeat.apply(null, [1])', TypeError);
+assertThrows('String.prototype.repeat.apply(undefined, [1])', TypeError);
+
+// Test cases found in FF
+assertEquals("abc", "abc".repeat(1));
+assertEquals("abcabc", "abc".repeat(2));
+assertEquals("abcabcabc", "abc".repeat(3));
+assertEquals("aaaaaaaaaa", "a".repeat(10));
+assertEquals("", "".repeat(5));
+assertEquals("", "abc".repeat(0));
+assertEquals("abcabc", "abc".repeat(2.0));
+
+assertThrows('"a".repeat(-1)', RangeError);
+assertThrows('"a".repeat(Number.POSITIVE_INFINITY)', RangeError);
+
+var myobj = {
+  toString: function() {
+    return "abc";
+  },
+  repeat : String.prototype.repeat
+};
+assertEquals("abc", myobj.repeat(1));
+assertEquals("abcabc", myobj.repeat(2));
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/harmony/string-startswith.js b/deps/v8/test/mjsunit/harmony/string-startswith.js
new file mode 100644 (file)
index 0000000..60c85d3
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-strings
+
+assertEquals(1, String.prototype.startsWith.length);
+
+var testString = "Hello World";
+assertTrue(testString.startsWith(""));
+assertTrue(testString.startsWith("Hello"));
+assertFalse(testString.startsWith("hello"));
+assertFalse(testString.startsWith("Hello World!"));
+assertFalse(testString.startsWith(null));
+assertFalse(testString.startsWith(undefined));
+
+assertTrue("null".startsWith(null));
+assertTrue("undefined".startsWith(undefined));
+
+var georgianUnicodeString = "\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10D7";
+assertTrue(georgianUnicodeString.startsWith(georgianUnicodeString));
+assertTrue(georgianUnicodeString.startsWith("\u10D0\u10D1\u10D2"));
+assertFalse(georgianUnicodeString.startsWith("\u10D8"));
+
+assertThrows("String.prototype.startsWith.call(null, 'test')", TypeError);
+assertThrows("String.prototype.startsWith.call(null, null)", TypeError);
+assertThrows("String.prototype.startsWith.call(undefined, undefined)", TypeError);
+
+assertThrows("String.prototype.startsWith.apply(null, ['test'])", TypeError);
+assertThrows("String.prototype.startsWith.apply(null, [null])", TypeError);
+assertThrows("String.prototype.startsWith.apply(undefined, [undefined])", TypeError);
+
+var TEST_INPUT = [{
+  msg: "Empty string", val: ""
+}, {
+  msg: "Number 1234.34", val: 1234.34
+}, {
+  msg: "Integer number 0", val: 0
+}, {
+  msg: "Negative number -1", val: -1
+}, {
+  msg: "Boolean true", val: true
+}, {
+  msg: "Boolean false", val: false
+}, {
+  msg: "Regular expression /\d+/", val: /\d+/
+}, {
+  msg: "Empty array []", val: []
+}, {
+  msg: "Empty object {}", val: {}
+}, {
+  msg: "Array of size 3", val: new Array(3)
+}];
+
+function testNonStringValues() {
+  var i = 0;
+  var l = TEST_INPUT.length;
+
+  for (; i < l; i++) {
+    var e = TEST_INPUT[i];
+    var v = e.val;
+    var s = String(v);
+    assertTrue(s.startsWith(v), e.msg);
+    assertTrue(String.prototype.startsWith.call(v, v), e.msg);
+    assertTrue(String.prototype.startsWith.apply(v, [v]), e.msg);
+  }
+}
+testNonStringValues();
+
+var CustomType = function(value) {
+  this.startsWith = String.prototype.startsWith;
+  this.toString = function() {
+    return String(value);
+  }
+};
+
+function testCutomType() {
+  var i = 0;
+  var l = TEST_INPUT.length;
+
+  for (; i < l; i++) {
+    var e = TEST_INPUT[i];
+    var v = e.val;
+    var o = new CustomType(v);
+    assertTrue(o.startsWith(v), e.msg);
+  }
+}
+testCutomType();
+
+// Test cases found in FF
+assertTrue("abc".startsWith("abc"));
+assertTrue("abcd".startsWith("abc"));
+assertTrue("abc".startsWith("a"));
+assertFalse("abc".startsWith("abcd"));
+assertFalse("abc".startsWith("bcde"));
+assertFalse("abc".startsWith("b"));
+assertTrue("abc".startsWith("abc", 0));
+assertFalse("abc".startsWith("bc", 0));
+assertTrue("abc".startsWith("bc", 1));
+assertFalse("abc".startsWith("c", 1));
+assertFalse("abc".startsWith("abc", 1));
+assertTrue("abc".startsWith("c", 2));
+assertFalse("abc".startsWith("d", 2));
+assertFalse("abc".startsWith("dcd", 2));
+assertFalse("abc".startsWith("a", 42));
+assertFalse("abc".startsWith("a", Infinity));
+assertTrue("abc".startsWith("a", NaN));
+assertFalse("abc".startsWith("b", NaN));
+assertTrue("abc".startsWith("ab", -43));
+assertTrue("abc".startsWith("ab", -Infinity));
+assertFalse("abc".startsWith("bc", -42));
+assertFalse("abc".startsWith("bc", -Infinity));
index 2b07954..d6ee3f2 100644 (file)
@@ -109,3 +109,14 @@ for(var i = 0; i < 1000; i++) {
 assertEquals(42, foo(-42));
 %OptimizeFunctionOnNextCall(foo)
 assertEquals(42, foo(-42));
+
+// Regression test for SMI input of Math.abs on X64, see:
+// https://codereview.chromium.org/21180004/
+var a = [-1, -2];
+function foo2() {
+  return Math.abs(a[0]);
+}
+assertEquals(1, foo2());
+assertEquals(1, foo2());
+%OptimizeFunctionOnNextCall(foo2);
+assertEquals(1, foo2());
similarity index 83%
rename from deps/v8/test/intl/general/v8Intl-exists.js
rename to deps/v8/test/mjsunit/regress/regress-264203.js
index 610767e..fa00756 100644 (file)
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Make sure that v8Intl is mapped into Intl for backward compatibility.
+// Flags: --allow-natives-syntax
 
-assertEquals(v8Intl, Intl);
+function foo(x) {
+  var a = [1, 2, 3, 4, 5, 6, 7, 8];
+  a[x + 5];
+  var result;
+  for (var i = 0; i < 3; i++) {
+    result = a[0 - x];
+  }
+  return result;
+}
 
-// Extra checks.
-assertTrue(v8Intl.hasOwnProperty('DateTimeFormat'));
-assertTrue(v8Intl.hasOwnProperty('NumberFormat'));
-assertTrue(v8Intl.hasOwnProperty('Collator'));
-assertTrue(v8Intl.hasOwnProperty('v8BreakIterator'));
+foo(0);
+foo(0);
+%OptimizeFunctionOnNextCall(foo);
+var r = foo(-2);
+assertEquals(3, r);
diff --git a/deps/v8/test/mjsunit/regress/regress-2813.js b/deps/v8/test/mjsunit/regress/regress-2813.js
new file mode 100644 (file)
index 0000000..97ae43b
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function foo(x) {
+  var a = x + 1;
+  var b = x + 2;
+  if (x != 0) {
+    if (x > 0 & x < 100) {
+      return a;
+    }
+  }
+  return 0;
+}
+
+assertEquals(0, foo(0));
+assertEquals(0, foo(0));
+%OptimizeFunctionOnNextCall(foo);
+assertEquals(3, foo(2));
diff --git a/deps/v8/test/mjsunit/regress/regress-omit-checks.js b/deps/v8/test/mjsunit/regress/regress-omit-checks.js
new file mode 100644 (file)
index 0000000..e5d5074
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var a = {x:1};
+var a_deprecate = {x:1};
+a_deprecate.x = 1.5;
+function create() {
+  return {__proto__:a, y:1};
+}
+var b1 = create();
+var b2 = create();
+var b3 = create();
+var b4 = create();
+
+function set(b) {
+  b.x = 5;
+  b.z = 10;
+}
+
+set(b1);
+set(b2);
+%OptimizeFunctionOnNextCall(set);
+set(b3);
+var called = false;
+a.x = 1.5;
+Object.defineProperty(a, "z", {set:function(v) { called = true; }});
+set(b4);
+assertTrue(called);
+assertEquals(undefined, b4.z);
similarity index 60%
rename from deps/v8/src/extensions/i18n/locale.h
rename to deps/v8/test/mjsunit/unary-minus-deopt.js
index c39568e..367ef75 100644 (file)
 // 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_
+// Flags: --allow-natives-syntax
+
+// This is a boiled-down example happening in the Epic Citadel demo:
+// After deopting, the multiplication for unary minus stayed in Smi
+// mode instead of going to double mode, leading to deopt loops.
+
+function unaryMinusTest(x) {
+  var g = (1 << x) | 0;
+  // Optimized code will contain a LMulI with -1 as right operand.
+  return (g & -g) - 1 | 0;
+}
+
+unaryMinusTest(3);
+unaryMinusTest(3);
+%OptimizeFunctionOnNextCall(unaryMinusTest);
+unaryMinusTest(3);
+assertOptimized(unaryMinusTest);
+
+// Deopt on kMinInt
+unaryMinusTest(31);
+// The following is normally true, but not with --stress-opt. :-/
+// assertUnoptimized(unaryMinusTest);
+
+// We should have learned something from the deopt.
+unaryMinusTest(31);
+%OptimizeFunctionOnNextCall(unaryMinusTest);
+unaryMinusTest(31);
+assertOptimized(unaryMinusTest);
index 4aaf8a9..a437e93 100644 (file)
@@ -33,3 +33,6 @@ sort-large-array: PASS, SKIP if $mode == debug
 
 ##############################################################################
 [ $deopt_fuzzer == True ]
+
+# Issue 2815.
+fast/js/kde/encode_decode_uri: SKIP
index 9719376..12ccefd 100755 (executable)
@@ -40,6 +40,7 @@ import re
 import struct
 import sys
 import types
+import v8heapconst
 
 USAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
 
@@ -163,6 +164,11 @@ 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.
 
@@ -754,6 +760,14 @@ 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
@@ -834,262 +848,6 @@ 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."""
 
@@ -2201,11 +1959,15 @@ 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 "")
index 0c1ad68..cbf9484 100644 (file)
         }],
         ['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',
           ],
           '../../src/arraybuffer.js',
           '../../src/typedarray.js',
           '../../src/generator.js',
-          '../../src/array-iterator.js'
+          '../../src/array-iterator.js',
+          '../../src/harmony-string.js',
+          '../../src/harmony-array.js',
         ],
         'i18n_library_files': [
           '../../src/extensions/i18n/header.js',
index 761d03f..48682d4 100755 (executable)
@@ -94,6 +94,9 @@ 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="")
@@ -204,6 +207,9 @@ 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
 
 
@@ -315,7 +321,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)
+    s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests)
     if options.cat:
       verbose.PrintTestSource(s.tests)
       continue
index a9a6203..d634e3e 100644 (file)
@@ -37,6 +37,7 @@ 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'
@@ -48,6 +49,7 @@ KEYWORDS = {SKIP: SKIP,
             TIMEOUT: TIMEOUT,
             CRASH: CRASH,
             SLOW: SLOW,
+            FLAKY: FLAKY,
             FAIL_OK: FAIL_OK,
             PASS_OR_FAIL: PASS_OR_FAIL}
 
index 634fe6a..1d30fe3 100644 (file)
@@ -42,6 +42,7 @@ 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 +50,7 @@ PASS_OR_FAIL = "PASS_OR_FAIL"
 ALWAYS = "ALWAYS"
 
 KEYWORDS = {}
-for key in [SKIP, FAIL, PASS, OKAY, TIMEOUT, CRASH, SLOW, FAIL_OK,
+for key in [SKIP, FAIL, PASS, OKAY, TIMEOUT, CRASH, SLOW, FLAKY, FAIL_OK,
             PASS_OR_FAIL, ALWAYS]:
   KEYWORDS[key] = key
 
@@ -68,6 +69,10 @@ 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))
 
index 473e8b1..b0372e7 100644 (file)
@@ -66,7 +66,10 @@ class TestSuite(object):
 
   # Used in the status file and for stdout printing.
   def CommonTestName(self, testcase):
-    return testcase.path
+    if utils.IsWindows():
+      return testcase.path.replace("\\", "/")
+    else:
+      return testcase.path
 
   def ListTests(self, context):
     raise NotImplementedError
@@ -84,32 +87,36 @@ class TestSuite(object):
   def ReadTestCases(self, context):
     self.tests = self.ListTests(context)
 
-  def FilterTestCasesByStatus(self, warn_unused_rules):
+  @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"):
     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)
-        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):
+        # Even for skipped tests, as the TestCase object stays around and
+        # PrintReport() uses it.
+        t.outcomes = self.rules[testname]
+        if statusfile.DoSkip(t.outcomes):
           continue  # Don't add skipped tests to |filtered|.
-      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"
+        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"
       filtered.append(t)
     self.tests = filtered
 
index f693467..00c330d 100644 (file)
@@ -54,7 +54,7 @@ def PrintReport(tests):
       skipped += 1
       continue
     if statusfile.TIMEOUT in o: timeout += 1
-    if statusfile.IsFlaky(o): nocrash += 1
+    if statusfile.IsPassOrFail(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/deps/v8/tools/v8heapconst.py b/deps/v8/tools/v8heapconst.py
new file mode 100644 (file)
index 0000000..591bf99
--- /dev/null
@@ -0,0 +1,252 @@
+# 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",
+  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",
+  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", 0x27585): "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", 0x0eb41): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x177a1): "JsEntryCode",
+}
diff --git a/deps/v8/tools/v8heapconst.py.tmpl b/deps/v8/tools/v8heapconst.py.tmpl
new file mode 100644 (file)
index 0000000..a773f47
--- /dev/null
@@ -0,0 +1,30 @@
+# 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.
+